Monitor SLOG to manage Synchronizing

Well… nothing I can see seems out of line.

Does calling the sync function directly result in the same lock up? If not does checking the SLOG lines like this but not calling the sync action produce the issue?

If its only the combination of the two, it may be that you’ve created a race condition by opening the slog and attempting to sync without a pause in between… but I can only speculate at this point.

2 Likes

The problem is the combination.

Syncing with that definition as isolated python node works:

image

doc = DocumentManager.Instance.CurrentDBDocument

def Sync():
	tOptions = TransactWithCentralOptions()
	rOptions = RelinquishOptions(False)
	rOptions.StandardWorksets = True
	rOptions.ViewWorksets = True
	rOptions.FamilyWorksets = True
	rOptions.UserWorksets = True
	rOptions.CheckedOutElements = True
	sOptions = SynchronizeWithCentralOptions()
	sOptions.SetRelinquishOptions(rOptions)
	sOptions.Compact = False
	sOptions.SaveLocalBefore = True
	sOptions.SaveLocalAfter = True
	sOptions.Comment = ""
	TransactionManager.Instance.ForceCloseTransaction()

	doc.SynchronizeWithCentral(tOptions, sOptions)

try:
	Sync()
	OUT= "success"
except:
	OUT="error"

Using my code without the syncing part and syncing with clockwork node is also working:

But using my full code and i am hooked again and can watch at my slog file that is getting bigger and bigger of the endless sync entries…

1 Like

I tried to end transactions after file reading and start a new transaction before syncing, with no difference in the result, I´m synclooping to infinity:


..........

with io.open(SlogFile,"r", encoding = "utf-16(LE)") as file:	
	SLOG = file.read().splitlines()
	TransactionManager.Instance.ForceCloseTransaction()
	
with io.open(LogFile,"r", encoding = "utf-8") as Logfile:	
	LOG = Logfile.read().splitlines()
	TransactionManager.Instance.ForceCloseTransaction()

........
			try:
				TransactionManager.Instance.EnsureInTransaction(doc)
				tOptions = TransactWithCentralOptions()
				rOptions = RelinquishOptions(False)
				rOptions.StandardWorksets = True
				rOptions.ViewWorksets = True
				rOptions.FamilyWorksets = True
				rOptions.UserWorksets = True
				rOptions.CheckedOutElements = True
				sOptions = SynchronizeWithCentralOptions()
				sOptions.SetRelinquishOptions(rOptions)
				sOptions.Compact = False
				sOptions.SaveLocalBefore = True
				sOptions.SaveLocalAfter = True
				sOptions.Comment = ""
				TransactionManager.Instance.ForceCloseTransaction()
				doc.SynchronizeWithCentral(tOptions, sOptions)

What else can i try? I have absolutely no idea than splitting this up in 2 python nodes :frowning:

This might be beneficial, as there are other commands which may want to happen after ensuring that no one is sycing (ie: transmitting a model; upgrading to a new version; saving a new central, etc.), but for the simplicity of combining the two… you may want to ensure that the SLOG is closed by the Python node, then wait a second (or more/less, depending on your network setup) before starting the swc… Attempting separate transactions won’t solve anything though, as the file would still be in use.

If closing the SLOG in the Python node, pausing a second and then executing the sync doesn’t work let m wknow and I’ll have to look on my end.

The “with” command should already make sure that the file is closed. Will add a pause tomorrow and try again.

Within the context of the Python graph; sure. But not necessarily withing the context of your Revit (and other users as well). Hence the thought that the belt and suspenders could help resolve things.

1 Like

Sending my code to sleep for 5 seconds will also send me back in the never ending syncloop.

Also a file.close() does not help.

So here is the isolated problem code, just an input to a slog file path needed. Would be nice if someone would take the time to test.

import io
import time
import clr
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

SlogFile = IN[0]

with io.open(SlogFile,"r", encoding = "utf-16(LE)") as file:	
	SLOG = file.read().splitlines()
	file.close()

for Line in SLOG:
	if "STC" in Line:
		if Line[-4:] == ">STC":
			# while loop will be added here
			OUT="Active Sync detected"
			
		elif Line[-4:] == "<STC":
			time.sleep(5.0)
			try:
				tOptions = TransactWithCentralOptions()
				rOptions = RelinquishOptions(False)
				rOptions.StandardWorksets = True
				rOptions.ViewWorksets = True
				rOptions.FamilyWorksets = True
				rOptions.UserWorksets = True
				rOptions.CheckedOutElements = True
				sOptions = SynchronizeWithCentralOptions()
				sOptions.SetRelinquishOptions(rOptions)
				sOptions.Compact = False
				sOptions.SaveLocalBefore = True
				sOptions.SaveLocalAfter = True
				sOptions.Comment = ""
				TransactionManager.Instance.ForceCloseTransaction()
				doc.SynchronizeWithCentral(tOptions, sOptions)
				OUT = "Sync Successful"
			except:
				OUT = "Sync did not work"
		else:
			OUT = "fail"

Encountering the next problem, now with a dialog box.
The dialog box is triggered even the if condition is not met.
And it is not triggered one time but ~100 times.

image


def UserMessage():

	taskDialog = ......
	
	return taskDialog.Show()

for Line in SLOG:
	if "STC" in Line:
		if Line[-4:] == ">STC":
			Result = UserMessage()
			if Result == TaskDialogResult.Yes:
				OUT="Whileloop"
			else:
				OUT="Canceled"
		elif Line[-4:] == "<STC":
			OUT = True		
		else:
			OUT = "fail"

Is there an obvious mistake or could it have to do something with the syncing problem? Because i think the sync problem is not invinite, just a very large amount of syncs. Why is everything running hundreds of times in my code :sweat_smile:

Problem with taskDialog solved, seems like that command was too deep in a for loop.
While loop is now working.

[video-to-gif output image]

for slog in SLOG:
	if "STC" in slog:
		if slog[-4:] == ">STC":
			toggle = False		
		elif slog[-4:] == "<STC":
			toggle = True
	else:
		outlist= ["a"]

if toggle is False:
	Result = UserMessage()
	if Result == TaskDialogResult.Yes:
		timeout = time.time() + 30 #seconds
		bool = True
		while bool == True:
			time.sleep(0.25) # sleep for 250 milliseconds
			if time.time() > timeout:
				OUT="break"
				break
			with io.open(SlogFile,"r", encoding = "utf-16(LE)") as file:
				SLOG = file.read().splitlines()	
				for slog in SLOG:
					if "STC" in slog:
						if slog[-4:] == "<STC":
							bool = False
						else:
							bool=True						
	else:
		resultout = "fail"
else:
	OUT = "fail"

Added everything i need except the syncing…

The workflow now is:

  • Read SLOG
  • Read QLOG (thats the name for my queue log)
  • Get last user of QLOG
  • Search for Session ID in SLOG
  • Test if there is an active sync
  • If active sync ask user if he wants to get queued
  • If yes, write QLOG entry and while loop SLOG until last QLOG user has finished syncing

There are for sure many additional things to consider, but it´s running, hopefully i will also solve the sync loop problem.

import io
import csv
import time
import clr
clr.AddReference("RevitAPI")
clr.AddReference('DynamoRevitDS')
clr.AddReference("RevitAPIUI")
import Dynamo
clr.AddReference('DSCoreNodes')
from Autodesk.Revit.UI import TaskDialog, TaskDialogCommonButtons, TaskDialogResult, TaskDialogCommandLinkId, TaskDialogIcon
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from datetime import datetime

doc = DocumentManager.Instance.CurrentDBDocument

def CreateLogEntry():
	dynamoRevit = Dynamo.Applications.DynamoRevit()
	currentWorkspace = dynamoRevit.RevitDynamoModel.CurrentWorkspace
	dynamoFileName = currentWorkspace.FileName
	
	dynamoRevit = Dynamo.Applications.DynamoRevit()
	currentWorkspace = dynamoRevit.RevitDynamoModel.CurrentWorkspace
	dynamoFileName = currentWorkspace.FileName
	app = DocumentManager.Instance.CurrentUIApplication.Application
	User = app.Username
	
	now = datetime.now()
	dateformat = "%d.%m.%Y"
	timeformat = "%X"
	Date = now.strftime(dateformat)
	Time = now.strftime(timeformat)
	
	CentralFilePath_dfs = BasicFileInfo.Extract(doc.PathName).CentralPath
	CentralFilePath = "P:\\"+(CentralFilePath_dfs.split("\\dfs\\")[1])
	
	FileNameList = CentralFilePath.Split("\\")
	FileNameListLength = len(FileNameList)
	FileName = FileNameList [FileNameListLength-1]
	
	ProjectList = FileName.Split("_")
	Projectnumber = ProjectList[0]

	string = Projectnumber+"\t"+User+"\t"+Date+"\t"+Time+"\t"+dynamoFileName
	return string
	
def WriteLogEntry():
	with io.open(QlogFilePath,"w", encoding="UTF8", newline='') as Qlogfile:	
		for Qlog in NewLog:
			writer = csv.writer(Qlogfile,delimiter="'")
			writer.writerow([Qlog])

def UserMessage():

	taskDialog = TaskDialog("Test1")
	taskDialog.MainInstruction = "User currently syncing"#"Ein Benutzer synchronisiert gerade."
	taskDialog.MainContent = "Want to get queued in the sync line?"#"In Synchronisations-Warteschlange einreihen?"
	taskDialog.TitleAutoPrefix = False	
	taskDialog.MainIcon = TaskDialogIcon.TaskDialogIconInformation	
	taskDialog.CommonButtons = TaskDialogCommonButtons.Cancel | TaskDialogCommonButtons.Yes	
	taskDialog.FooterText = "Help"
	
	return taskDialog.Show()
	
CentralFilePath_dfs = BasicFileInfo.Extract(doc.PathName).CentralPath
CentralFilePath = "P:\\"+(CentralFilePath_dfs.split("\\dfs\\")[1])

FileNameList = CentralFilePath.Split("\\")
FileNameListLength = len(FileNameList)
FileName = FileNameList [FileNameListLength-1]
SlogFileName = FileName.Replace("rvt","slog")

ProjectList = FileName.Split("_")
Projectnumber = ProjectList[0]


SlogFileFolder = CentralFilePath.Replace(".rvt","_backup")
SlogFile = SlogFileFolder+"\\"+SlogFileName
QlogFilePath = "..................."

with io.open(SlogFilePath,"r", encoding = "utf-16(LE)") as SlogFile:	
	SLOG = SlogFile.read().splitlines()
	
with io.open(QlogFilePath,"r", encoding = "utf-8") as Qlogfile:	
	QLOG = Qlogfile.read().splitlines()
NewLog = QLOG
bla=CreateLogEntry()
NewLog.append(bla)
		
SLOG.reverse()	

for qlog in QLOG:
	if Projectnumber in qlog:
		QLOG_LastItem = qlog
		QLOG_LastUser = QLOG_LastItem.split("\t")[1]
for slog in SLOG:
	if "user=" and QLOG_LastUser in slog:
		Index = SLOG.index(slog)
SessionIdOfLastQLOGUser = SLOG[Index+1][:9]

for slog in SLOG:
	if SessionIdOfLastQLOGUser in slog:
		SessionIndex=SLOG.index(slog)

LastUser = SLOG[SessionIndex-1].split('"')[1::2][0]

SLOG.reverse()

for slog in SLOG:
	if "STC" in slog:
		if slog[-4:] == ">STC":
			toggle = False		
		elif slog[-4:] == "<STC":
			toggle = True
	else:
		outlist= ["a"]

if toggle is False:
	Result = UserMessage()
	if Result == TaskDialogResult.Yes:
		timeout = time.time() + 60 #seconds
		WriteLogEntry()
		bool = True
		while bool == True:
			time.sleep(0.25) # sleep for 250 milliseconds
			if time.time() > timeout:
				OUT="break"
				break
			with io.open(SlogFilePath,"r", encoding = "utf-16(LE)") as SlogFile:
				SLOG = SlogFile.read().splitlines()	
				for slog in SLOG:
					if "STC" and SessionIdOfLastQLOGUser in slog:
						if slog[-4:] == "<STC":
							bool = False
						else:
							bool=True						
	else:
		resultout = "fail"
else:
	OUT = "fail"

OUT = QLOG_LastItem, QLOG_LastUser, SessionIdOfLastQLOGUser, LastUser, toggle, bool, bla, NewLog

Syncing problem solved also :slight_smile:
Same problem, it didnt like to be in a for> if loop, so i created again the “workaround” to define outputs for different conditions and then test the output in an extra if loop:

import io
import time
import clr
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

SlogFile = IN[0]

with io.open(SlogFile,"r", encoding = "utf-16(LE)") as file:	
	SLOG = file.read().splitlines()
	file.close()

for Line in SLOG:
	if "STC" in Line:
		if Line[-4:] == ">STC":
			x=1
			
		elif Line[-4:] == "<STC":
			x=2
			
		else:
			x=3
if x==2:			
	try:
		tOptions = TransactWithCentralOptions()
		rOptions = RelinquishOptions(False)
		rOptions.StandardWorksets = True
		rOptions.ViewWorksets = True
		rOptions.FamilyWorksets = True
		rOptions.UserWorksets = True
		rOptions.CheckedOutElements = True
		sOptions = SynchronizeWithCentralOptions()
		sOptions.SetRelinquishOptions(rOptions)
		sOptions.Compact = False
		sOptions.SaveLocalBefore = True
		sOptions.SaveLocalAfter = True
		sOptions.Comment = ""
		TransactionManager.Instance.ForceCloseTransaction()
		doc.SynchronizeWithCentral(tOptions, sOptions)
		OUT = "Sync Successful"
	except:
		OUT = "Sync did not work"
1 Like

Looks like I managed to create a failed sync entry in the slog, which leads to a fail of my code.
Will be interresting to find out how i will handle such failed entries…

$c6a82d43 2022-10-15 00:15:09.355 >STC
$c6a82d43 2022-10-15 00:15:09.713 >STC:RL
$c6a82d43 2022-10-15 00:15:09.947 .STC:RL:LockRoot  RW locked
$c6a82d43 2022-10-15 00:15:10.007 >STC:RL:HC
$c6a82d43 2022-10-15 00:15:10.161 .STC:RL:HC:LockUsers  R locked
$c6a82d43 2022-10-15 00:15:11.470 .STC:RL:HC:LockUsers  R unlocked
$c6a82d43 2022-10-15 00:15:11.731 <STC:RL:HC
$c6a82d43 2022-10-15 00:15:12.201 .STC:RL:CFV  central=185

$fc1d59a2 2022-10-15 00:21:50.969 >Session  $fc1d59a2

Because Testing with multiple Revit sessions is hard enough i added a dictionary to the output to better understand whats going on.

Here another test under “lab conditions” in a larger model.
It seems that managed syncing with dynamo is not a real solution.

Simultaneous syncing:

Overall Time: 217 seconds
User split: 43, 217, 148, 85 seconds

Managed syncing with dynamo:

Overall Time: 320 seconds
User split: 78, 162, 233, 320 seconds

$3846b44a 2022-10-15 18:52:01.894 >STC
$3846b44a 2022-10-15 18:53:18.269 <STC

$892cefa0 2022-10-15 18:53:21.216 >STC
$892cefa0 2022-10-15 18:54:42.675 <STC

$39c2031f 2022-10-15 18:54:44.847 >STC
$39c2031f 2022-10-15 18:55:53.131 <STC

$4279e0bb 2022-10-15 18:55:55.603 >STC
$4279e0bb 2022-10-15 18:57:18.999 <STC

Managed syncing in general:

If the users would not be trapped in dynamo during the waiting time, with no ability to work, we would get a timesplit of about 80/80/80/80 seconds. That would be the best result. Would this be possible with a plugin?

Yes. If you want to not lock up the Revit UI you need to move past Dynamo.

To complicate things a big more, you’d need to move past a standard Revit add-in and into one with the add-in components and an external service monitoring the queue and results, which would then send the sync command back over to the add-in to trigger the sync. While possible, this gets to be problematic as if a user has an active action (say editing a sketch or group) the external command cannot be triggered nor can a sync. That means the 3rd person in line is stuck waiting for not only the first sync to finish, but also the second person’s group edit to finish and their sync…

3 Likes

Oh yes that being in an active action problem is a deal breaker.

So i think that chapter is closed for now, will see if someone in my company wants to do further testing of the python script, but in the end it`s not a real problemsolver.

Anyway, it was a fun project! Thank you for all your help jacob! :slight_smile:
Here the full code:

import io
import csv
import time
import clr
clr.AddReference("RevitAPI")
clr.AddReference('DynamoRevitDS')
clr.AddReference("RevitAPIUI")
import Dynamo
clr.AddReference('DSCoreNodes')
from Autodesk.Revit.UI import TaskDialog, TaskDialogCommonButtons, TaskDialogResult, TaskDialogCommandLinkId, TaskDialogIcon
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from datetime import datetime

doc = DocumentManager.Instance.CurrentDBDocument

def QLOG_New_Entry():
	dynamoRevit = Dynamo.Applications.DynamoRevit()
	currentWorkspace = dynamoRevit.RevitDynamoModel.CurrentWorkspace
	dynamoFileName = currentWorkspace.FileName
	
	dynamoRevit = Dynamo.Applications.DynamoRevit()
	currentWorkspace = dynamoRevit.RevitDynamoModel.CurrentWorkspace
	dynamoFileName = currentWorkspace.FileName
	app = DocumentManager.Instance.CurrentUIApplication.Application
	User = app.Username
	
	now = datetime.now()
	dateformat = "%d.%m.%Y"
	timeformat = "%X"
	Date = now.strftime(dateformat)
	Time = now.strftime(timeformat)
	
	CentralFilePath_dfs = BasicFileInfo.Extract(doc.PathName).CentralPath
	CentralFilePath = "P:\\"+(CentralFilePath_dfs.split("\\dfs\\")[1])
	
	FileNameList = CentralFilePath.Split("\\")
	FileNameListLength = len(FileNameList)
	FileName = FileNameList [FileNameListLength-1]
	
	ProjectList = FileName.Split("_")
	Projectnumber = ProjectList[0]

	QLOG_New_Entry = Projectnumber+"\t"+User+"\t"+Date+"\t"+Time+"\t"+dynamoFileName
	return QLOG_New_Entry

def Read_SLOG():
	with io.open(SlogFilePath,"r", encoding = "utf-16(LE)") as SlogFile:	
		SLOG = SlogFile.read().splitlines()
		return SLOG

def Read_QLOG():
	with io.open(QlogFilePath,"r", encoding = "utf-8") as Qlogfile:	
		QLOG = Qlogfile.read().splitlines()
		return QLOG
	
def Write_QLOG_Entry():
	with io.open(QlogFilePath,"w", encoding="UTF8", newline='') as Qlogfile:	
		for Qlog in QLOG_New:
			writer = csv.writer(Qlogfile,delimiter="'")
			writer.writerow([Qlog])

def UserMessage():

	taskDialog = TaskDialog("Test1")
	taskDialog.MainInstruction = "User currently syncing"#"Ein Benutzer synchronisiert gerade."
	taskDialog.MainContent = "Want to get queued in the sync line?"#"In Synchronisations-Warteschlange einreihen?"
	taskDialog.TitleAutoPrefix = False	
	taskDialog.MainIcon = TaskDialogIcon.TaskDialogIconInformation	
	taskDialog.CommonButtons = TaskDialogCommonButtons.Cancel | TaskDialogCommonButtons.Yes	
	taskDialog.FooterText = "Help"
	
	return taskDialog.Show()
	
def Sync():

	try:
		tOptions = TransactWithCentralOptions()
		rOptions = RelinquishOptions(False)
		rOptions.StandardWorksets = True
		rOptions.ViewWorksets = True
		rOptions.FamilyWorksets = True
		rOptions.UserWorksets = True
		rOptions.CheckedOutElements = True
		sOptions = SynchronizeWithCentralOptions()
		sOptions.SetRelinquishOptions(rOptions)
		sOptions.Compact = False
		sOptions.SaveLocalBefore = True
		sOptions.SaveLocalAfter = True
		sOptions.Comment = ""
		TransactionManager.Instance.ForceCloseTransaction()
		doc.SynchronizeWithCentral(tOptions, sOptions)
		return "Sync Successful"
	except:
		return "Sync did not work"
	
CentralFilePath_dfs = BasicFileInfo.Extract(doc.PathName).CentralPath
CentralFilePath = "P:\\"+(CentralFilePath_dfs.split("\\dfs\\")[1])

FileNameList = CentralFilePath.Split("\\")
FileNameListLength = len(FileNameList)
FileName = FileNameList [FileNameListLength-1]
SlogFileName = FileName.Replace("rvt","slog")

ProjectList = FileName.Split("_")
Projectnumber = ProjectList[0]

SlogFileFolder = CentralFilePath.Replace(".rvt","_backup")
SlogFilePath = SlogFileFolder+"\\"+SlogFileName
QlogFilePath = "......................"

SLOG = Read_SLOG()	
QLOG = Read_QLOG()

SLOG_LastItemIndex = len(SLOG)-1
		
SLOG.reverse()	

for qlog in QLOG:
	if Projectnumber in qlog:
		QLOG_LastItem = qlog
		QLOG_LastUser = QLOG_LastItem.split("\t")[1]

QLOG_New = QLOG
QLOG_New_Entry = QLOG_New_Entry()
QLOG_New.append(QLOG_New_Entry)

Write_QLOG_Entry()

for slog in SLOG:
	if "user="+"\""+ QLOG_LastUser +"\"" in slog:
		SessionUserIndex = SLOG.index(slog)
		SessionUserLine = SLOG[SessionUserIndex]

SessionIdOfLastQLOGUser = SLOG[SessionUserIndex+1][:9]


for slog in SLOG:
	if SessionIdOfLastQLOGUser in slog:
		SessionIndex=SLOG.index(slog)

LastUser = SLOG[SessionIndex-1].split('"')[1::2][0]

SLOG.reverse()

for slog in SLOG:
	if "STC" in slog:
		Last_STC_Line = slog
		if Last_STC_Line[-4:] == "<STC":
			SyncActive = False
		else:
			SyncActive = True

if SyncActive is False:
	syncresult = Sync()
	LastSTCofSession = "none"
	bool = "none"
	

Session_STC_List=[]

if SyncActive is True:
	UserResult = UserMessage()
	if UserResult == TaskDialogResult.Yes:
		timeout = time.time() + 240 #seconds
		bool = True
		while bool == True:
			time.sleep(0.5) # sleep for 500 milliseconds
			if time.time() > timeout:
				syncresult="timeout"
				break
			with io.open(SlogFilePath,"r", encoding = "utf-16(LE)") as SlogFile:
				SLOG = SlogFile.read().splitlines()
				SLOG_Sublist = SLOG[SLOG_LastItemIndex:]
				for slog in SLOG_Sublist:
					if SessionIdOfLastQLOGUser in slog:					
						if "STC" in slog:
							LastSTCofSession = slog
							Session_STC_List.append(slog)
							if LastSTCofSession[-4:] == "<STC":
								bool = False		
							else:
								bool = True						
	else:
		outlist.append("Canceled by User")
else:
	OUT = "fail"
	
if bool is False:
	syncresult = Sync()
	
TaskDialog.Show("Results", syncresult)

dict = {"QLOG_LastItem": QLOG_LastItem, "QLOG_New_Entry":QLOG_New_Entry, "SessionUserLine":SessionUserLine,"SessionIdOfLastQLOGUser":SessionIdOfLastQLOGUser, "LastUser":LastUser,"SyncActive":SyncActive,"bool":bool,"LastSTCofSession":LastSTCofSession,"syncresult":syncresult,"Session_STC_List":Session_STC_List}

OUT = dict

Edit:

Again a failed STC entry because of closing revit:

$ccd7e64b 2022-10-20 22:54:10.386 >STC

$ccd7e64b 2022-10-20 22:54:10.427 >STC:RL

$ccd7e64b 2022-10-20 22:54:10.666 .STC:RL:LockRoot  RW locked

$ccd7e64b 2022-10-20 22:54:10.709 >STC:RL:HC

$ccd7e64b 2022-10-20 22:54:10.865 .STC:RL:HC:LockUsers  R locked

$ccd7e64b 2022-10-20 22:54:11.551 .STC:RL:HC:LockUsers  R unlocked

$ccd7e64b 2022-10-20 22:54:11.686 <STC:RL:HC

$ccd7e64b 2022-10-20 22:54:11.793 .STC:RL:CFV  central=2478

$319fb657 2022-10-20 23:04:55.771 .LockUsers  R locked

I will change my code to only check the last 10 minutes of the SLOG, so failed entries will not mess um everything.

2 Likes