I often read that profile documents are problematic as their major benefit is also their worst problem - caching.
There is a simple solution to that problem, which I extensively use. I’m a big fan of profile documents as they allow to share environment information very efficiently and also to tailor applications having one single application template for very different databases according to the needs of departments and groups. As we know caching is session based, which implements that if you open a session to read a specific value from a profile document, you read what at that moment is actually the value of that field independent who, how and when it was last updated. As I have several databases reading/writing in profile documents of other databases as well as in their own, sometimes an overlapping of running agents trying to read or write the same value in a specific profile document might happen. To make sure that just one agent works on a specific profile document at the time I set up the following function:
<<<<
Function GetProfileValue(Server As String, RepID As String, ProfileName As String, FieldName As String) As Variant
Dim NCProfDoc As NotesDocument
Dim NCSession As New NotesSession
Dim ncdb As New NotesDatabase("","")
If ncdb.OpenByReplicaID(Server,RepID) Then
Set NCProfDoc = ncdb.GetProfileDocument(ProfileName)
GetProfileValue = NCProfDoc.getitemvalue(FieldName)
Else
GetProfileValue = ""
End If
End Function
This function is in all my databases part of the script library and simply called “NoCache”.
As explained I use this function in my lotus scripts to make sure that the concurrent agents are “waiting” until another agent has finished his job. To make sure that all the agents know what’s going on I simple “lock” the specific filed in the profile document by setting its first value to “locked”. As long as this value is locked, a loop is going to check the value until it is unlocked by the running agent with control of that field. I just want to show here the part of the script where the value reading is made:
<<<<
If Not(cdbProfDoc Is Nothing) And (count = 0) Then
SCU = ";" + Join(Fulltrim(GetProfileValue(MServer,Left(RepID,8) + Right(RepID,8),"Database Profile","SC_Users")),";") + ";"
While Instr(SCU,";locked;") And (count < 300)
If (ACLL(0) = "Yes") And (count Mod 30 = 0) Then
Call ACLLog.LogError(0,"Agent is waiting as user list is locked in database " + cdb.Title)
End If
count = count + 1
Sleep (1)
SCU = ";" + Join(Fulltrim(GetProfileValue(MServer,Left(RepID,8) + Right(RepID,8),"Database Profile","SC_Users")),";") + ";"
Wend
If (count > 0) And (ACLL(0) = "Yes") Then
Call ACLLog.LogError(0,"Agent was restarted after the user list was unlocked in database " + cdb.Title)
End If
count = 0
End If
As you can see from that formula, I can use that function to read any list of values (in this case “SC_Users”) in any profile document (in this case “Database Profile”) in any database (in this case having the Replication ID stored in a variable called “RepID”, which must be a valid Replica ID given as a string) on any server (in this case having the name of the server stored in a variable called “MServer”, which could also be an empty string if your agent is running on the same server than the database to be read from). I read the list of values into a single string variable separating the values with “;”, this could be done in any other way as well.
If an agent has to lock the value to make sure that he is the only one writing to the list of values this is done by the following sequence:
<<<<
If count = 0 Then
cdbProfDoc.SC_Users = Fulltrim(Split("locked" + SCU,";"))
Call cdbProfDoc.Save(True, False, False)
End If
count = count + 1
Where cdbProfDoc was set to be the same profile document as read with the function “GetProfileValue”.
At the end the agent is unlocking the value by the following sequence:
<<<<
If count > 0 Then
While Instr(SCU,";locked;")
SCU = Fulltrim(Strleft(SCU,";locked;") + ";" + Strright(SCU,";locked;"))
Wend
cdbProfDoc.SC_Users = Fulltrim(Split(SCU,";"))
End If
The presented function can be used in any agent or other lotusscript feature at any time to make sure that the user gets actual data from the profile document, when this is a need.