Lade...
 

Entladen und Laden einer ClassiX®-Datenbank

Entladen und Laden einer ClassiX®-Datenbank

1. Zielstellung und Ablauf

2. Aufruf der Programme

2.1 Aufrufparameter des Programms CXUOSR.EXE (Entladen)

2.2 Aufrufparameter für CXCOSR.EXE (Prüfsummenbildung)

2.3 Aufrufparameter des Programms CXLOSR.EXE (Laden)

2.4 Beispiel – ein Batchfile

3. Clustering

4. Datenbankanalyse

5. Cross-Referenz der Objekte

 

1. Zielstellung und Ablauf

Die Datenbank wird beim Entladen in sequentielles Files im ASCII-Format geschrieben (DATABASE.DMP, FREEOBJ1.DMP, ...), die prinzipiell auch für Menschen lesbar sind. Sie enthalten alle Information über die Objekte der Datenbank, die notwendig sind, um diese Objekte in einer neuen Datenbank mit den gleichen Daten wieder aufzubauen und alle Beziehungen zwischen den Objekten zu rekonstruieren. Dabei kann die Verteilung der Objekte auf Teildatenbanken, Segmente und Cluster verändert werden – dies ist meist auch das Ziel einer solchen Operation.
Entladen – Laden bietet sich auch als Alternative zur der von ObjectStore vorgesehenen Schema-Evolution an (Umstellung der Datenbank auf ein neues Schema, d.h. veränderte Klassendefinitionen). Beim Entladen geht folgende Information verloren:

  • Objekte, die nicht mehr erreicht werden können (weder über eine Root-Entrypoint-Collection noch über Relation, die von mindestens einem anderen erreichbaren Objekt ausgeht
  • Indizes über Collections (einschließlich des Index-Managers)

Logisch gelöschte Objekte bleiben jedoch erhalten, solange sie noch von einem aktiven Objekt direkt oder indirekt referenziert werden.

Der Gesamtablauf – unter Einbeziehung einer die logische Integrität sichernden Prüfsummenbildung – umfasst vier Teilschritte:

  • Entladen mit Programm CXUOSR.EXE
    In Phase 1 werden alle Objekte in den Root-Entrypoint-Collections entladen. In Phase 2 wird für jedes bisher entladenen Objekt festgestellt, ob von diesem ausgehende Relationen auf ein noch nicht entladenes Objekt verweisen, das dann entladen wird. Da auch solche Objekte den eben genannten Test durchlaufen, ist das Verfahren transitiv und am Ende der Phase 2 sind alle über irgendwelche Zugriffspfade erreichbaren Objekte entladen. Dazu wird eine Hash-Table der (Datenbank-)Adressen aller bereits entladenen Objekte benötigt (TMPFILE.DMP). Die in Phase 1 entladenen Objekte finden wir in File DATABASE.dmp, die Objekte aus Phase 2 in den Files FREEOBJ1.dmp, FREEOBJ2.dmp, ... Für die Klassen CX_BITMAP, CX_COM_OBJECT und CX_MULTIPLE_COM_OBJECT entsteht pro Objekt ein weiteres File, das den Datenstrom des Objekts enthält.  
    Phase 3 ist optional: hier wird die Zuordnung der Objekte in den Root-Entry-Point-Collections in das File REP_COLLS.dmp gerettet. 
  • Checksumme der "alten Datenbank" bilden mit CXCOSR.EXE (Parameter –1)
    Alle Objekte des Datenbank werden segmentweise gelesen und mit einer Prüfsumme bewertet. Beim Lesen der Segmente werden auch unerreichbare Objekte "gesehen", mit der Hashtable, die beim Entladen aufgebaut wurde, können sie von erreichbaren Objekten unterschieden werden.
  • Laden der neuen Datenbank mit CXLOSR.EXE
    Auch das Wiederherstellen der Datenbank erfolgt in zwei Phasen. In Phase 1 werden alle Objekte erzeugt und den Datenfelder die entsprechenden Werte zugewiesen. Phase 2 ist für die Rekonstruktion der Beziehungen zwischen den Objekten zuständig. Damit dies möglich ist, wird in Phase 1 ein Hash-Table mit den Datenbank-Adressen aller Objekte aufgebaut – ähnlich wie beim Entladen – jedoch enthält hier jeder Eintrag ebenfalls die Datenbankadresse der neuen Datenbank: Verweise in der "alten Datenbank" können so sehr schnell in Verweise in die "neue Datenbank" übersetzt werden.
    Die Einordnung der neu Objekte in die Root-Entrypoint-Colelctions kann über die Beschreibung im CLASSIX.INI-File gesteuert werden - und damit auch gegenüber der entladenen Originaldatenbank verändert werden - oder mittels der beim Entladen in Phase 3 gesicherten Information identisch wiederhergestellt werden.
  • Checksumme der "neuen Datenbank" mit CXCOSR.EXE (Parameter –2)
    Für jedes Objekt in der neu geladenen Datenbank wird eine Prüfsumme berechnet. Übereinstimmung mit der Prüfsumme der "alten Datenbank" gibt die Garantie dafür, dass die Datenfelder aller Objekte richtig wiederhergestellt wurden. Außerdem wird die Zahl der von jedem Objekt ausgehenden Relationen bewertet, womit die Wiederherstellung der Objektbeziehung ebenfalls kontrolliert wird.
    Bei Abweichungen ist es möglich, die betroffenen Objekte in beiden Datenbanken anzusehen.

load9.GIF (14767 Byte)
Dies ist der Ablauf, wenn Phase 3 des Entlade- und Ladeprogramms nicht benutzt wird, d.h. die Anordnung der Objekte in den Root-Entrypoint-Collections durch die Angaben in CLASSIX.INI bestimmt wird. Das explizite Einfügen der Objekte in Phase 3 garantiert eine absolut identische Zuordnung der Objekte zu den Root-Entrypoint-Collections (siehe Ablauf).

Hinweis: Nur wenn die totale Prüfsumme in CHECKSUM.OLD und CHECKSUM.NEW identisch sind, kann die neu aufgebaute Datenbank an Stelle der entladenen "alten" Datenbank benutzt werden.

2. Aufruf der Programme

Alle Flags können mit / oder beginnen. Klein- und Großbuchstaben sind gleichbedeutend. Ein auf ein Flag folgender Parameter kann direkt anschließen oder durch Blanks getrennt sein; zum Beispiel:

cxuosr /iTS.INI /h5000000

oder

cxuosr –I ts.ini /H 5000000

Die Programme liefern bei Erfolg den Rückkehr-Code 0.

2.1 Aufrufparameter des Programms CXUOSR.EXE (Entladen)

Parameter Bedeutung Standardannahme
/I fileName Initialisierungsdatei CLASSIX.INI
/W fileName Hash-Table TMPFILE.DMP
/D workDir Arbeitsverzeichnis, in das alle anderen Files geschrieben bzw. aus dem sie gelesen werden aktuelles Directory
/Hn Geschätzte Anzahl n der Objekte in der Datenbank 47977
/F Hash-Table im Speicher halten (Fast mode) Hash-Table als File
/EparamFile Hash-Table auf externen DCOM-Servern Hash-Table als File
/1 nur Phase 1 Phase 1 und 2
/2 nur Phase 2 Phase 1 und 2
/3 Phase 3  
/Cn Pattern für Clustering 0xff oder Wert der Environement-Variblen CX_CLUSTERING
/Mn Berechnet die Speichergröße der Hash-Table für n Objekte. Damit kann man abschätzen, ob eine große Datenbank mit -F bzw. -E entladen werden kann.  

Die beiden Phasen

  • Entladen der Objekte aus den Root-Entrypoint-Collections
  • Entladen all jener Objekte, die nur über bisher entladene Objekte erreicht werden können

laufen automatisch hintereinander ab, wenn weder /1 noch /2 angegeben wurde.
Beim Entladen wird bestimmt, wie die Objekte in der neu aufzubauenden Datenbank in Clustern zusammengefasst werden.
Phase 3 sammelt die Information über die Anordnung der Objekte in den Root-Entrypoint-Collections.

Phase 1 ist restartfähig. Voraussetzung: Hash-Tabelle wird speicher-resident geführt (Parameter /E oder /F).
Wenn nach dem Ablauf eines vorgegebenen Zeitintervalls eine Klasse vollständig entladen wurde, wird die Hash-Tabelle als File 'filename.nnn' gerettet, mit nnn = { 001, 002, ...    }und in das Entladefile ein Kennzeichen geschrieben (Checkpoint).
An solch einem Punkt kann wieder aufgesetzt werden: Parameter /R. Die dabei entstehenden Teilstücken der Entladedaten müssen am Ende zusammengefügt werden, wobei überflüssige Informationen (zwischen letztem Checkpoint und Abbruch entladene Daten) eliminiert werden - Aufruf mit Parameter /P.
Die folgende Übersicht zeigt alle weiteren, für die Restartfähigkeit relevanten Flags:

Parameter Bedeutung Standardannahme
-Vn Zeitintervall (n in Sekunden) für Restart -V7200  (d.h. 2 Stunden)
-RclassName,k Restart nach Klasse 'className', k = { 1, 2, ... } ist die fortlaufende Nummer des Restartversuchs  
-Pfile1{restartInfo1},file2{restartInfo2},...,filen,outFile Files nach n-1 mal Restart zusammenkopieren, redundante Daten eliminieren  

Als 'restartInfo' ist der Filename des geretteten Hashfiles (vollständiger Pfad) anzugeben (siehe Beispiel).

2.2 Aufrufparameter für CXCOSR.EXE (Prüfsummenbildung)

Parameter Bedeutung Standardannahme
/I fileName Initialisierungsdatei CLASSIX.INI
/W fileName Hash-Table (von CXUOSR.exe) TMPFILE.dmp
/G fileName Hash-Table (von CXLOSR.exe) GATEWAY.dmp
/D workDir Arbeitsverzeichnis, in das alle anderen Files geschrieben bzw. aus dem sie gelesen werden aktuelles Directory
/1 Prüfsumme der "alten" Datenbank bilden keine
/2 Prüfsumme der "neuen" Datenbank bilden keine
/U fileName Hash-Table von CXUOSR.EXE (nur bei /1) TMPFILE.DMP
/F Hash-Table im Speicher halten (Fast mode) als File
/EparamFile Hash-Table auf externen DCOM-Servern als File

Die Prüfsummen für jedes einzelne Objekt werden bei /1 in das File OBJECTS.OLD geschrieben. Wenn CXCOSR.EXE für die neue Datenbank mit /2 läuft, entsteht noch das File OBJECTS.NEW, das alle Objekte mit ihren Prüfsummen enthält, wobei Prüfsummendifferenzen so gekennzeichnet sind, dass man sich mit InstantView® die betroffenen Objekte sowohl in der alten als auch in der neuen Datenbank ansehen kann – z.B. mit dem Objekt-Inspektor – InstantView®-Source: CHECKSUM.CXP. Weitere Funktionen für die Analyse von Objekten in alter und neuer Datenbank stellt das CX_DB_UTILITY-Objekt zur Verfügung.

Das Programm CXCOSR.EXE stellt eine weitere Funktionen zur Verfügung, die nicht direkt zum Entladen-Laden einer Datenbank gehört: den Aufbau einer Objekt-Cross-Referenz – d.h. einer Hilfsdatenbank, mit der für jedes Objekte festgestellt werden kann, von welchen anderen Objekten es referenziert wird

2.3 Aufrufparameter des Programms CXLOSR.EXE (Laden)

Parameter Bedeutung Standardannahme
/I fileName Initialisierungsdatei CLASSIX.INI
/G fileName Hashfile (Gateway von alter zu neuer Datenbank) GATEWAY.dmp
/D workDir Arbeitsverzeichnis, in das alle anderen Files geschrieben bzw. aus dem sie gelesen werden aktuelles Directory
/H nObjekte Geschätzte Anzahl der Objekte in der Datenbank 47977
/F Hash-Table im Speicher halten (Fast mode) als File
/EparamFile Hash-Table auf externen DCOM-Servern als File
/N Objekte beim Laden (Phase 1) noch NICHT in Root-Entrypoint-Colelctions eintragen, Phase 3 ist notwending Objekte gleich in REP-Colls einfügen, Phase 3 NICHT benutzen
/1 nur Phase 1 (Laden, Objekte erzeugen) Phase 1 und 2
/2 nur Phase 2 (Relationen rekonstruieren) Phase 1 und 2
/3 Phase 3 (Objekt in REP-Collections einfügen)  
/U zu bereits bestehender Datenbank "dazuladen" Datenbank wird neu erzeugt
/batch in Phase 1: neue Datenbank(en) erzeugen (und gleichnamige Datenbank(en) löschen) ohne interaktive Bestätigung interaktive Abfrage (muss mit 'YES' beantwortet werden)
/Mn Berechnet die Speichergröße der Hash-Table für n Objekte. Damit kann man abschätzen, ob eine große Datenbank mit -F geladen werden kann.  

Auch hier laufen im Normalfall (weder /1 noch /2 angegeben) beide Phasen automatisch hintereinander ab. CXLOSR.EXE erzeugt ein Protokoll im File LOAD.LOG

Die Hash-Tabelle (GATEWAY.DMP) bildet die Brücke zwischen alter und neuer Datenbank, d.h. für jede Objekt-Location in der alten Datenbank ist die Location des entsprechenden Objekts in der neu geladenen Datenbank bekannt. Die Tabelle kann während des Ladens resident im Speicher gehalten werden: lokal (Flag /F) oder verteilt auf externe Server (Flag /E). Ein "verteiltes Gateway-File" kann zu einem File zusammengefasst werden.

2.4 Beispiel – ein Batchfile

cxuosr -Its.ini
if ERRORLEVEL 1 goto ABEND
cxuosr -3 -Its.ini
if ERRORLEVEL 1 goto ABEND
cxcosr -1 -its.ini
if ERRORLEVEL 1 goto ABEND
cxlosr -its.ini -batch
if ERRORLEVEL 1 goto ABEND
cxlosr -its.ini -3
if ERRORLEVEL 1 goto ABEND
cxcosr -2 -its.ini
echo "Database sucessfully reloaded"
pause
exit
:ABEND
echo "Reload failed"

3. Clustering

Bei ObjectStore ist der Datentransfer zwischen dem Datenbank-Server und den Clients pageorientiert. Deshalb bestimmt die Anordnung der Objekte in der Datenbank in hohem Maße die Performance der Anwendungen.

Das Clustering der Objekte ist steuerbar für

Für beide Fälle kann das Clustering stufenweise aktiviert bzw. deaktiviert werden.

Unter dem Aspekt des Clustering ist ein Objekt entweder ein Master- oder Slave-Objekt:

Ein Masterobjekt wird in einem für seine Klasse festgelegtem Segment der Datenbank gespeichert; möglicherweise wird für das Masterobjekt ein Cluster angelegt. Die Information über das Segment und ein eventuell anzulegende Cluster sind im Datenbank-Layout (File CLASSIX.ODB) beschrieben.

Wenn das Clustering vollständig deaktiviert ist gibt es nur Masterobjekte – dies ist die Standardannahme im ClassiX®-System.

Die Position eines Slaveobjektes in der Datenbank bestimmt ein anderes, bereits in der Datenbank gespeichertes Objekt, mit dem es verbunden wird. Die Erzeugung solch eines Objekts mit CreatePersObject, CopyPersObject muss verzögert werden bis zu dem Zeitpunkt, wenn eine Relation zu einem bereits in der Datenbank existierenden Objekt aufgebaut wird. Die genannten InstantView®-Befehle erzeugen deshalb zunächst ein (transientes) Objekt der Klasse CX_LAZY_CREATOR.
Der Ablauf beim Entladen / Laden einer Datenbank ist davon abweichend und wird im folgenden beschrieben.
 

Zuvor soll aber auf die Regeln eingegangen werden, mit denen bestimmt wird, wann ein Objekt Master ist und wann nicht.

Die Clustering-Regeln wurden – nach pragmatischen Gesichtspunkten – in Kategorien zusammengefasst, und, in dem jeder Kategorie ein Bit zugeordnet wird, erhält man ein Pattern, mit dem die Kategorien unabhängig voneinander ein- und ausgeschaltet werden können.

Dieses Pattern wird mit der Environment-Variablen CX_CLUSTERING gesetzt; Standardannahme ist CX_CLUSTERING=0.

Die folgende Tabelle zeigt die Kategorien und die damit verbundenen Regeln; neben dem Bit in Spalte 1 wurde in der zweiten Spalte ein Name vergeben.

Spalte 3 gibt an, welche Klassen als Slaveobjekte auftreten können. Während bei elementaren Objekten (z.B. der Basisklassen CX_DATE, CX_VALUE ...) die Klassenzugehörigkeit als alleiniges Kriterium genügt, werden für komplexere Objekte Zusatzbedingungen angegeben:

Bit Kategorie Klassen Bedingung
1 BASIC CX_NUMERIC..., CX_VECTOR_AMOUNT..., CX_TERM..., CX_FORMULA, CX_FCONDITION, CX_NAMED_FCONDITION, CX_CONDITIONED_BAG

aber nicht CX_NAMED_FORMULA

-
2 VALIDITY CX_VALIDITY... -
4 WRAPPER CX_DESCRIPTIVE_REF, CX_OVERWRITING_REF -
8 SLAVE_SEG alle kein eigenes Objektsegment
16 ZEROPATTERN CX_ATTRIBUTE_SET... REP_pattern = 0
32 ZEROPATTERN CX_PASSWORD..., CX_GENERAL_TERMS..., CX_CONDITION..., CX_ACCESS... REP_pattern = 0
64 TXN CX_TRANSACTION... REP_pattern = 0 &

(if ($ transaction ) transaction = master

else master is a CX_TRANSACTION)

    CX_ALLOCATION... REP_pattern = 0 &

if (card allocators > 0) master Î allocators

else true

128 MONITOR CX_ACCOUNT... if ($ owner) owner = master else true
    CX_DATA_CUBE...
Dimension[0] = master

 

  • A... bedeutet Klasse A und alle davon abgeleiteten Klassen
  • REP_pattern ist das Bit-Pattern, das die Einordnung des Objekts in die REP-Collection bestimmt; entweder vorgegeben durch die Beschreibung der Klasse in CLASSIX.ODB oder durch explizite Angabe bei CreatePersObject
  • Bedingungen, die sich auf das Masterobjekt master beziehen, gelten nur beim Entladen/Laden, bei CreatePersObject / CopyPersObject wird immer ein CX_LAZY_CREATOR erzeugt
  • Wenn ein Objekt mit CreatePersObject erzeugt wird, gilt für alle Kategorien die Zusatzbedingung REP_pattern = 0. Ein transientes Objekt CX_LAZY_CREATOR kann nicht in eine REP-Collection eingefügt werden.


Die obengenannten Regeln sollen nicht nur das mittels verzögerter Objekterzeugung (CreateOersObject -> CX_LAZY_CREATOR) hergestellte Clustering steuern sondern natürlich auch beim Entladen/Laden einer Datenbank wirksam sein.

Die Anordnung der Objekte in der neuen Datenbank wird bereits beim Entladen bestimmt:

Wird ein Masterobjekt o entladen, so werden alle von ihm über Relationen (Pointer / Collections) direkt erreichbaren Objekte or nach den obengenannten Regeln getestet, wobei Objekte o die Rolle des Masters übernimmt. Sind unter den Objekten or Slaveobjekte, werden diese als nächste entladen und im Entlade-File als zu o gehörig gekennzeichnet.

Beim Entladen der Slaveobjekte geschieht das gleiche, die or übernehmen die Rolle des Masters und alle von diesen erreichbaren Objekte werden getestet, ob sie sich von or "clustern lassen". Auch diese indirekt erreichten Objekt kommen in das zu Objekt o gehörende Cluster. Objekt o bestimmt dann beim Laden der Datenbank, wie alle ihm untergeordneten Objekte zu speichern sind.

Ein gerade entladenes Objekt o "fragt" alle von ihm referenzierten Objekte, ob sie sich von o "clustern lassen".

Dementsprechend ist es wichtig, in welcher Reihenfolge die Objekte entladen werden.

Beim Entladen werden den Klassen Prioritätenzahlen (von 0 bis 5) zugeordnet. In Phase 1 werden alle Objekte aus den in Root-Entrypoint-Collections entladen, wobei Klassen mit niedrigen Prioritätszahlen zuerst kommen:

Prioritätszahl  
0 CX_ATOM_TABEL, CX_UNIT_PARAMETER
1 CX_MULTIPLE_COM_OBJECT
2 REP_pattern in CLASSIX.ODB > 0 und 0, 1, 4 oder 5 trifft nicht zu
3 REP_pattern in CLASSIX.ODB > 0 und 0, 1, 4 oder 5 trifft nicht zu
4 CX_DESCRIPTIVE_REF, CX_OVERWRITING_REF
5 CreatePersObject würde CX_LAZY_CREATOR erzeugen

Innerhalb der gleichen Kategorie werden die Klassen entsprechend der Reihenfolge der Klassenbeschreibungen in CLASSIX.ODB entladen, d.h.
auch die Reihenfolge der Class-Anweisungen in CLASSIX.ODB beeinflusst das Clustering.

 

4. Datenbankanalyse

Wenn die Datenbank auch nur ein korruptes Objekt enthält, wird der Entladevorgang im allgemeinen mit einem Programmfehler abbrechen.

Programm CXAOSR.EXE kann in einem Analyselauf solche Fehler entdecken und in eine Report-File schreiben:

Parameter Bedeutung

Standardannahme

/I fileName Initialisierungsdatei CLASSIX.INI
/D workDir Arbeitsverzeichnis, in das alle anderen Files geschrieben bzw. aus dem sie gelesen werden aktuelles Directory
/A Analyse der gesamten Datenbank keine
/AsegmentName Analyse nur für das angegebene Segment keine
/AsegX-segY Analyse ab Segment segX bis segY keine
/AsegX- Analyse ab Segment segX bis Ende keine
/A-segY Analyse (ab Anfang) bis Segment segY (einschließlich)  
/An%-m% bzw. /An%- oder /A-%m
wie oben, Segmente segX, segY mit Prozentangabe relativ zur Größe der Datenbank auswählen:
segX entspricht n % der Datenbankgröße, segY entspricht m%; Bedingung n < m
keine
/R Analyse aller REP-Collections keine
/R repName Analyse der REP-Collection mit dem angegebenen Namen  
/P iptFile1,iptFile2,...,iptFilen,outFile,xRefFile[,W]
Postprocessing Analyze-Files, es werden nur Fehler übernommen, die sich auf korrupte Objekte beziehen, File zur Steuerung der partiellen X-Referenz wird erzeugt, 'W' = kopiert 'WRAPPER' in dieses File /Panalyze.lst,analyze2.lst,xObjects.lst

Beispiel: Analyseläufe für eine große Datenbank auf drei PCs verteilen: cxaosr /A-33%, cxaosr /A34%-66%, cxaosr /A67%-

Hinweis: In einem Batch-File an die Syntax der Parameter denken: die Prozentzeichen verdoppeln, also z.B.: cxaosr /A34%%-66%% angeben!

Bei der Analyse (mit Flag /A...) wird für jedes Objekt die virtuelle Funktion SanityCheck() aufgerufen. Ein Rückkehrcode > 0 signalisiert einen Fehler:

Slots

1 Slot: Pointer auf Daten = NULL (oder dynamic_cast schlägt fehl)
2 Slot: Pointer korrupt (mapping into real memory fails)
3 Slot – unbekannter Datentyp (nicht im Dictionary)
4 Fehler im Frame: n < g
5 Fehler im Frame: n < 0 oder g < 0
6 Fehler im Frame: g > 0 aber kein Slotvektor allokiert
7 DeleteSlot hat Datenpointer nicht zurückgesetzt (auf NULL) ... harmlos
8 Slotname = 0
9 dynmischer Slot (siehe. AssignSlot) - Slot nicht im Dictionary
10 dynmischer Slot (siehe. AssignSlot) - keine Beziehung zu definierendem Ausdruck
13 anonymous Slot (siehe CX_OVERWRITING_REF) - kein Bezug zu überschreibendem Ausdruck


Objekte

20 - 22 CXB_MULTIPLE_STRING: Widerspruch Anzahl - allokierte Strings
24 CXB_MULTIPLE_STRING: Teilstring nicht derefenzierbar
30, 31 CX_NUMERIC korrupt
32 Unit korrupt
33 Wert 94967254 !!!
41 CX_DESCRIPTIVE_REF und abgeleitete – Pointer auf "Wrapper" korrupt
(dynamic_cast schlägt fehl)
42 CX_DESCRIPTIVE_REF und abgeleitete – Pointer auf "Wrapper" korrupt
(mapping into real memory fails)
50 CX_EXPANDABLE und abgeleitete - classID falsch
71-73 CX_SPAN_DATE
80, 81 CX_PERIODIC_DATE
85, 86 CX_DATETIME
87-89 CX_GLOBAL_DATETIME
100-107 CX_LOCALE ...
391 CX_FORMULA – Ausdruck widerspricht Syntax
400 CX_CONDITIONED_BAG – Kette der CX_FCONDITIONs korrupt
(dynamic_cast schlägt fehl)
401 CX_CONDITIONED_BAG mit "fremdem" CX_FCONDITION (fCond->parent != this)
402 CX_CONDITIONED_BAG – Kette der CX_FCONDITIONs korrupt
(mapping into real memory fails)
501 CX_COM_OBJECT ohne Daten (persistentDataStream == NULL)
511 CX_MULTIPLE_COM_OBJECT enthält mindestens ein CX_COM_OBJECT ohne Daten

SanityCheck ruft sich selbst auch für im DDI eingetragene Member auf, sofern es sich um ein Objekt handelt. Bei einem Fehler wird Original-Errorcode + 10000 zurückgegeben.

Außerdem werden Relationen zu anderen Objekten analysiert (Funktion CheckReferences):

Error  
285 aktives Objekt referenziert (logisch) gelöschtes Objekt
286 (logisch) gelöschtes Objekt referenziert aktives Objekt
287 Referenz korrupt (dynamic_cast schlägt fehl)
316 Referenz korrupt (ObjectStore Exception)
317 Referenz korrupt (undefinierte Exception - mit catch(...) gefangen)
318 NULL Pointer in Collection
319 Coll. korrupt (undefinierbarer Fehler, mit catch(...) gefangen)
376 Coll. mit Cardinality c < 0 bzw. c > 10 000 000
377 Coll. - endlose Iteration
378 Coll. mit Cardinality um 1 zu groß
379 Coll. mit zu großer Cardinality
380 Coll. mit zu kleiner Cardinality
207 Typ des referenzierten Objekts widerspricht DDI / Slot-Dictionary (Pointer)
211 Typ des referenzierten Objekts widerspricht DDI / Slot-Dictionary (Collection)
2001 ObjectStore Exception schon bei Aufruf der Funktion SanityCheck() oder CheckReferences()
2002 undefinierte Exception schon bei Aufruf der Funktion SanityCheck() oder CheckReferences()

Funktionen des CX_DB_UTILITY-Objekts unterstützen eine effektive Analyse des Fehlerprotokolls.

 

5. Cross-Referenz der Objekte

Oft wäre es von Interesse, für ein bestimmtes Objekt o alle Objekte or zu kennen, die das Objekte o referenzieren, d.h. alle Objekte or die einen Pointer auf o oder eine Collection mit o als Element besitzen.

Diese Information wird in Objekten der Klasse CX_XREF gehalten. Aufbau einer Cross-Rererenz bedeutet, dass für jedes Objekt genau ein CX_XREF-Objekt erzeugt wird, das auf alle Objekte verwiest, die das vom CX_XREF-Objekt repräsentierte Objekte referenzieren.

Es ist sinnvoll, die CX_XREF-Objekte in einer separaten physischen Datenbank zu halten - sie stellen ja nur eine Momentaufnahme dar, die bald ihre Aktualität verliert. CX_XREF-Objekte verweisen auf "normale" Objekte - aber nicht umgekehrt. Die physische Teildatenbank für die Cross-Referenz kann deshalb jederzeit wieder gelöscht werden, ohne Auswirkung auf die "eigentliche" Datenbank.

Die Zuordnung  eines Objektes zu "seinem" CX_XREF-Objekt ist außerhalb der Datenbank realisiert (im Gateway-File).
Die Funktion GetObjectsReferringTo() des Objektmanagers liefert für ein als Parameter übergebenem Objekt o eine Collection alle Objekte or, die das Objekt o referenzieren.

Für ein solches Objekt o, auf das sich kein einziges anderes Objekt or bezieht, entsteht auch kein korrespondierendes Objekt der Klasse CX_XREF, es sei denn, man verlangt mit Flag /O, dass für jedes Objekt ein CX_XREF-Objekt entstehen soll, um damit "einsame" Objekt in der Datenbank zu finden.

 

Beschreibung einer Hilfsdatenbank für die Cross Referenz:

MetaInfo
Database(2, CX_XREFDB)

Segment(xrefS, DB(2))

Class(CX_XREF, 51, xref)

File(xref, xref, xref)

Storage(xref, DB(2), xrefS, EP("xrefL0"(LIST)), CSeg(xrefS), Garbage(xrefG0, xrefS))

Diese Beschreibung wird - solange man mit der Cross-Referenz arbeiten will - dem Initialisierungsfile (z.B. classix.ini) hinzugefügt.

Hinweis:
Aus Gründen der Performance sollte die REP-Collection der CX_XREF-Objekt vom Typ LIST sein.
Für jedes Objekt in der Ausgangsdatenbank, das von anderen Objekten referenziert wird (das sind die meisten) entsteht ein korrespondierendes Objekt CX_XREF. Das Einfügen in ein SET verbraucht bei einer wachsenden Anzahl von Objekten immer mehr Zeit.

Bei großen Datenmengen sollte für das Objektsegment ein Grenzwert für Segmentsplitting angegeben werden.

Für die Cross-Referenz der dynamischen Datenfelder entstehen in der Hilfsdatenbank Objekte der Klasse CX_SLOT_XREF. Metainformation für Objekt- und Slot-Cross-Referenz zeigt folgendes Beispiel.

Die Objekt-Cross-Referenz wird aufgebaut, indem mit

    ...

    SET CX_XREFDB=myXReferenceDB.cxd

    cxgosr –U –I modifiziertesIniFile.ini –batch

die Teildatenbank für Hilfsobjekte angelegt wird.

 

Danach wird mit CXXOSR.EXE die Cross-Referenz aufgebaut:

Parameter Bedeutung Standardannahme
/X n Cross-Referenz, n geschätzte Anzahl der Objekte  n = 47977
/X n,objectFile Cross-Referenz, n geschätzte Anzahl der Objekte, die im File bezeichneten Objekt werden ignoriert (Ausblenden) n = 47977
/X objectFile partielle Cross-Referenz, d.h. nur für die im File angegebene Objekte  
/S nur die Cross-Referenz für dynamische Datenfelder bilden Cross-Referenz für Objekte
/B Cross-Referenzen für Objekt und für dynamische Datenfelder in einem Lauf  nur Cross-Referenz für Objekte
/O Hilfsflag für das Aufsammeln von Orphan-Objekten, jetzt entsteht für jedes Objekt der Datenbank ein zugehöriges CX_XREF-Objekt  CX_XREF-Objekt werden nur für referenzierte Objekt erzeugt
/I fileName (modifizierte) Initialisierungsdatei CLASSIX.INI
/G fileName Hashfile (Gateway von alter zu neuer Datenbank) objects.xrf
/F Hash-Table im Speicher halten (Fast mode) als File
/EparamFile Hash-Table auf externen DCOM-Servern als File
/D workDir Arbeitsverzeichnis, in das alle anderen Files geschrieben bzw. aus dem sie gelesen werden aktuelles Directory

 

Die Funktion GetObjectsReferringTo() benötigt das Gateway-File. 
Auf mehrere externe DCOM-Server verteilte Gateway-Files (Parameter /E) können deshalb mit Programm CXXOSR.EXE zusammengefasst werden:

Parameter Bedeutung Standardannahme
/Cntotal,gatewayFile1,n1,gatewayFile2,n2,... kopiert alle Teil-Dateien nach GATEWAY.CON  

Die korrekte Angabe der Teilgrößen (n1 + n2 + ... = ntotal) wird mit den Angaben in den Files gatewayFilek verglichen.  

Beispiel-Batch-Files für den Aufbau der vollständigen Cross-Referenz finden Sie hier.


Partielle Cross-Referenz:
Der Aufbau der Objekt-Crossreferenz wird beschleunigt, wenn nur für eine bestimmte Menge von Objekten { o1, o2, ... } ermittelt wird, welche Objekte or eines der vorgegebenen Objekte { o1, o2, ... } referenzieren. Im Parameter /X wird ein File angegeben, das

  • in der ersten Zeile die geschätzte Anzahl n der Objekte und optional den Bezeichner EXCLUDE enthält
  • in den folgenden Zeilen die Objekte mittels ihrer Location in der Datenbank vorgibt

Aus der Anzahl n wird die Primzahl für das Hashfile berechnet - ein größeres n verbessert die Performance.
Mit EXCLUDE wird gefordert, dass die vorgegebenen Objekte nicht als potentielle Referenten getestet werden. Das ist sinnvoll bei Reparaturen korrupter Objekte in der Datenbank: Man möchte wissen, welche Objekte auf die "korrupten" Objekte verweisen, diese aber vom Test ausschließen.

Beispiel:

2000, EXCLUDE <0|284|0|80f230|10000>, <0|284|0|80f350|10000>, <0|284|0|80f470|10000>, <0|284|0|80f590|10000>, <0|284|0|80f7e0|10000>, <0|284|0|80fa20|10000>, <0|284|0|80fb40|10000>, <0|284|0|80fc60|10000>, <0|284|0|80fd80|10000>, <0|284|0|810360|10000>, <0|284|0|8105bc|10000>, <0|284|0|8106ec|10000>, <0|284|0|810800|10000>, <0|284|0|810920|10000>, <0|284|0|810a40|10000>, <0|284|0|810b60|10000>, <0|284|0|810c80|10000>, <0|284|0|810da0|10000>, <0|284|0|810ec0|10000>, <0|284|0|81157c|10000>, <0|284|0|811914|10000>, <0|284|0|811a84|10000>, <0|284|0|812040|10000>, <0|284|0|812268|10000>, <0|284|0|812320|10000>, <0|504|0|7d13cc|10000>

Kommata als Trennzeichen zwischen den Elementen sind optional.    
Die Anzahl der Objekte pro Zeile ist beliebig, solange eine Zeilenlänge von 512 Zeichen nicht überschritten wird.

Bestimmte Objekte ausblenden:
Auch bei der vollständigen Cross-Referenz kann man einzelne Objekt ausschließen. Diese Variante ist vor allem als Hilfsmittel für den Fall gedacht, dass man sich mit korrupte Objekten in der Datenbank auseinandersetzen muss. Aufbau des File wie oben angegeben.

Datenbank-Analyse und partielle Cross-Referenz bilden zusammen ein Werkzeug mit dem logisch oder physisch korrupte bzw. inkonsistente Objekte in einer Datenbank "repariert" werden können (Beispiel-Ablauf).  

Hinweis: Mittels der Crossreferenz kann ein Objekt in der Datenbank durch ein anderes Objekt ersetzt werden (Funktion Substitute des DB-Utility-Objekts).