Lade...
 

CX_OBJECT_DICTIONARY...::FixKeyOwnership

CX_OBJECT_DICTIONARY...::FixKeyOwnership

220621
Beschreibung:

Diese Methode implementiert den für alle Object-Dictionaries notwendigen Reorg-Lauf, damit Dlls ≥ 220415 mit Object-Dictionaries arbeiten können, die vorher angelegt und manipuliert wurden. Da in den vorherigen Dll-Versionen die Dictionary-Keys nicht korrekt kopiert wurden und ihren Speicher beim Löschen nicht freigegeben haben, müssen in diesem Reorg-Lauf alle Einträge neu angelegt werden, damit diese beim Manipulieren des Dictionaries nicht doppelt gelöscht werden.

Der Reorg kopiert alle Einträge des Dictionaries in eine transiente Kopie. Anschließend werden alle Dictionary-Keys aus dem persistenten Dictionary gelöscht und aus dem transienten Dictionary neu angelegt. Dieser Vorgang kann je nach Anzahl der Einträge mehrere Minuten dauern (1 Mio. Einträge ~ 5 Minuten). Die Änderungen müssen durch einen Transaktionscommit anschließend noch zur Datenbank übertragen werden, was für ein Dictionary mit 1Mio. Einträgen ebenfalls im Bereich 2-3 Minuten liegt.

Um zu verhindern, dass das Transaktionslog vollläuft, sollte nach jedem verarbeiteten Dictionary die Transaktion commited werden.

Als erster Parameter kann optional eine beliebig gewählte Progress-ID übergeben werden, die dazu führt, dass ein Progress-Fenster für die Dauer der Prozedur geöffnet wird und einen Überblick über den groben Fortschritt gibt. Die Zeitabschätzung wird jedoch nicht auf Basis der zu kopierenden Einträge vorgenommen, weswegen sie recht ungenau ist. Wird hier "" oder NULL als Parameter übergeben, dann wird kein Progress-Fenster geöffnet.

Der Reorg kann gefahrlos mehrfach auf einem Dictionary ausgeführt werden, dies führt nicht zu inskonsistentem verhalten. Leider lässt sich mangels Zugriffs auf die interne Datenstruktur des ObjectStore-Dictionaries nicht im Vorfeld ermitteln, ob der Reorg notwendig ist, wodurch er auch beim zweiten Durchlauf in vollem Umfang durchgeführt und das Dictionary vollständig neu aufgebaut wird.

Nachdem der Reorg ausgeführt wurde, kann auch gefahrlos wieder auf eine ältere Dll-Version gewechselt werden (dadurch entstehen lediglich wieder Speicherlecks). Wird anschließend wieder auf eine neuere Version gewechselt, dann muss der Reorg jedoch erneut ausgeführt werden.

223222 funktioniert dieser Reorg auch dann noch korrekt, falls Schlüssel der Hinrelation auf gelöschten oder neu zugewiesenen Speicher zeigen und der Speicher wird in dem Fall nicht freigegeben (was zu einer korrupten Datenbank führen könnte). Zudem werden auf dem Logger cx.model.dict die gefundenen Probleme geloggt.

Achtung: Die Dictionary-Kopie wird aus den Daten der Rückrelation aufgebaut. Falls ein nicht reorganisiertes Dictionary über längere Zeit mit Dlls ≥ 220415 verwendet wurde, dann können auch die Daten aus der Rückrelation beschädigt werden und in dem Fall bricht der Reorg mit einem Fehler ab, da sich das Dictionary nicht kopieren lässt.
Ein solches Dictionary sollte dann nicht mehr verwendet werden, da jeder Zugriff darauf potenziell zu einem Absturz führen kann.

Ergänzende Hinweise:

Nach dem Lauf von FixKeyOwnership kann osverifydb vermehrt folgende Fehler melden.

The object at <d|basisdo2:Y:\classix\CxOffice\Projects\classix.cxd|1158|72|230|10000> (type "CX_ODICT_STRING_UTF16"), contains a pointer at <d|basisdo2:Y:\classix\CxOffice\Projects\classix.cxd|1158|72|238|10000> (CX_ODICT_STRING_UTF16.value) incorrectly pointing to an object of mismatched type at <d|basisdo2:Y:\classix\CxOffice\Projects\classix.cxd|1158|72|240|10000>; the declared type "2 byte unsigned short" is incompatible with the type of the target object (char[0]). The type of this object is "1 byte char". The object at <d|basisdo2:Y:\classix\CxOffice\Projects\classix.cxd|1158|72|3f8|10000> (type "CX_ODICT_STRING_UTF16"), contains a pointer at <d|basisdo2:Y:\classix\CxOffice\Projects\classix.cxd|1158|72|400|10000> (CX_ODICT_STRING_UTF16.value) incorrectly pointing to deleted object at <d|basisdo2:Y:\classix\CxOffice\Projects\classix.cxd|1158|72|408|10000>.

Diese Einträge sind völlig normal, falls sich das CX_OBJECT_DICTIONARY_... im gleichen Cluster befindet, wie die CX_ODICT_STRING_UTF16-Objekte, zu denen die Fehler gemeldet werden. Falls:

"<0|1158|72|0|10000>" GrabObject

in ClassiX also ein CX_OBJECT_DICTIONARY... liefert (der Offset der DB-Adresse muss hierfür lediglich auf 0 gesetzt werden), dann handelt es sich bei diesen Objekten um fehlerhaft persistent angelegte temporäre Schlüsselobjekte, die nicht referenziert und seit der Korrektur der Speicherverwaltung aus Dll-Version 220415 auch nicht mehr angelegt werden. 

Die ungültigen Pointer können in dem Fall per:

osverifydb.exe -F -illegal_pointer_action null -segment_n 1158 classix.cxd > repair.log

durchgenullt und die Fehler damit behoben werden.

 

Code-Beispiel:

Das nachfolgende Codebeispiel zeigt, wie alle Dictionaries einer Datenbank reorganisiert werden können. Da die Dicitonaries per FindAll gesucht werden, werden hier keine Dictionaries gefunden, die nicht in der entsprechenden REP registriert sind. Solche Dictionaries könnte man noch per CollectObjects oder CollectInSegment versuchen zu finden.

Var(dicts) // collect all dictionaries [ "Collecting dictionaries..." TIME_ELAPSED ] Progress(SHOW) CreateTransCollection(LIST) -> dicts [ CX_OBJECT_DICTIONARY CX_OBJECT_DICTIONARY_CI CX_OBJECT_DICTIONARY_ML CX_OBJECT_DICTIONARY_ML_CI ] iterate(BACKWARD) { FindAll(STACK) dicts Insert } // optionally save list of dictionaries to file / load from file dicts "CX_SYSTEM_OUT\\dicts.coll" GetManager(OBJECT) Call(GetDBUtility) Call(DumpCollection) "CX_SYSTEM_OUT\\dicts.coll" 0 (-1) GetManager(OBJECT) Call(GetDBUtility) Call(LoadCollectionDump) -> dicts Var(nDicts) dicts Cardinality -> nDicts // reorganize each dictionary dicts iterate(UNSAFE) { LocalVar(dict) -> dict [ "Reorganizing Dictionary" Index 1 + nDicts ] Progress(SHOW) // run reorg for this dictionary and pass progress id to display sub progress "fix" dict Call(FixKeyOwnership) [ "Commiting transaction" ] Progress(SHOW) EndTXN BeginTXN } Progress(CLOSE)
Stack
Stack Position Objekttyp Kurzbeschreibung
Stack(In) Top CX_OBJECT_DICTIONARY... Das zu reogranisierende Dictionary
  Top-1 STRING optionale ID für Progress-Fenster
Wenn "" oder NULL, dann wird kein Progress-Fenster geöffnet
Stack(Out) Top - -
Funktionsaufruf: Call(FixKeyOwnership)