analyzeRawLockChronologyFile(); constants MinUserClassNum = 2048; MaxUserClassNum = 999999; LockTypeValues = 'Shared Reserved Exclusive Update'; vars cmd : CMDFileOpen; file : File; line : String; token : String; recType : Integer; pos : Integer; // record fields nodeInstID : String; dbUserIndex : String; ticks : Integer64; lockReqType : Integer; classNum : Integer; instId : String; parentClassNum : Integer; subLevel : String; subId : String; edition : String; processInstId : String; lockType : Integer; lockDuration : Integer; // end record fields lockTypes : StringArray; log : JadeLog; oidString : String; infoDict : DynaDictionary; refOid : Object; refInfo : JadeDynamicObject; infoString : String; begin create cmd transient; cmd.fileMustExist := true; //for some reason on windows 10 forward slashes don't work for the initial directory cmd.initDir := node.getJadeWorkDirectory().replace__('/', '\', true); if cmd.open() <> 0 then write 'no file - exit'; return; endif; create file transient; file.fileName := cmd.fileName; file.mode := File.Mode_Input; file.kind := File.Kind_Unknown_Text; if file.tryOpen() then create log transient; log.versionFile:= false; log.formatOutput := false; log.fileName := 'lock-chronology.log'; create infoDict transient; infoDict.setMembership(JadeDynamicObject); infoDict.addExternalKey(Object, 0, false, true); infoDict.endKeys(true); lockTypes := LockTypeValues.getTokens(); while not file.endOfFile do line := file.readLine(); if line.length() <= 0 then continue; endif; pos := 1; token := line.getNextToken(pos); recType := token.Integer; if recType <> 22 then continue; endif; nodeInstID := line.getNextToken(pos); dbUserIndex := line.getNextToken(pos); ticks := line.getNextToken(pos).Integer64; lockReqType := line.getNextToken(pos).Integer; if lockReqType <> 2 and lockReqType <> 3 then continue; // a get or put object or something else. we just want lock and unlock. endif; classNum := line.getNextToken(pos).Integer; instId := line.getNextToken(pos); parentClassNum := line.getNextToken(pos).Integer; // reduce noise if (parentClassNum <> 0 and parentClassNum < MinUserClassNum) or classNum < MinUserClassNum then continue; endif; if (parentClassNum <> 0 and parentClassNum > MaxUserClassNum) or classNum > MaxUserClassNum then continue; endif; subLevel := line.getNextToken(pos); subId := line.getNextToken(pos); edition := line.getNextToken(pos); processInstId := line.getNextToken(pos); lockType := line.getNextToken(pos).Integer; lockDuration := line.getNextToken(pos).Integer; oidString := classNum.String & '.' & instId; if parentClassNum <> 0 then oidString := oidString & '.' & parentClassNum.String & '.' & subLevel & '.' & subId; endif; // get the reference information once per refOid := oidString.asOid; refInfo := infoDict.getAtKey(refOid).JadeDynamicObject; if refInfo = null then if parentClassNum <> 0 then infoString := getPropInfo(parentClassNum, subLevel.Integer, subId.Integer); else infoString := rootSchema.getClassByNumber(classNum).name & ' instance'; endif; create refInfo transient; refInfo.addProperty('info', String); refInfo.setPropertyValue('info', infoString); infoDict.putAtKey(refOid, refInfo); else infoString := refInfo.getPropertyValue('info').String; endif; if lockReqType = 2 then line := ' lock '; else line := 'unlock '; // we only grabbed 2 and 3 endif; line := line & oidString; if lockType > 0 and lockType < 5 then line := line & ' ' & lockTypes[lockType]; else line := line & ' = ' & lockType.String; endif; line := line & ' : ' & infoString; log.info(line); endwhile; file.close(); else write 'file open failed: fileName = ' & file.fileName; endif; epilog delete file; delete cmd; delete lockTypes; infoDict.purge(); delete infoDict; end;