Scheduled Agent to determine when user last accessed mail file stops too soon

The good news is that given any person doc, this agent will go to the server, find their mail file in the location specified, and determine the date that that particular user accessed his/her mail file.

If all we had to do were spot checks it’d work great but when scheduling this agent to run on every document (13,000 users) in order to produce a sorted report, it terminates early.

If run as a scheduled agent on the server, it craps out at around 175 users (person docs), if run manually from a workstation, it poops out at around 60 users (person docs)

any ideas?

thks,

-MC

Option Public

Option Explicit

Use “CLASSUserActivity”

Sub Initialize

Dim ua As NotesUserActivity

Dim uae As NotesUserActivityEntry

Dim iCounter As Long

Dim filenum As Integer, test As Integer, lenname As Integer



Dim hwnd As Long

Dim i As Long

Dim j As Long

Dim dbsize As Notesdatabase

'The Following Dim is uncommented in the manually run version

'Dim uiw As New NotesUIWorkspace 

'The Following Dim is uncommented in the manually run version

'Dim uidoc As NotesUIDocument



Dim sess As New NotesSession, session As New NotesSession, s As New NotesSession

Dim coll As notesdocumentcollection

Dim db As New notesdatabase("", "") 

Set db = sess.currentdatabase

Set coll = db.unprocesseddocuments

Dim newDoc As Notesdocument, doc1 As Notesdocument, doc2 As Notesdocument, docA As Notesdocument, docB As Notesdocument

Dim names As NotesDatabase

Dim longname As String

Dim db1 As New notesdatabase("","")    

fileNum% = Freefile()



Set docA = coll.getfirstdocument

Set docB = docA

’ Dim boxType As Long, answer As Integer

’ boxType& = 36

’ answer% = Messagebox(“Do you want to continue?”, boxType&, _

’ “Continue?”)

’ If (answer%=7) Then

’ Exit Sub

’ End If

Open "C:\active.log" For Output As fileNum%

While Not (docB Is Nothing)

	test=0

	Print  #filenum%, + Now()+ " Mail Activity for :"+ docB.MailFile(0) + ".nsf : " + docB.MailServer(0)

	

	On Error Goto Errortrap          

	Set db1 = s.GetDatabase(docB.MailServer(0),docB.MailFile(0) )

	If Not db1.IsOpen Then 

		Call docB.replaceitemvalue ("LastAccess", "No DB")     

		Call docB.save(True,True)

		Print  #filenum%, + Now()+ " Error opening file :"+ docB.MailFile(0) + ".nsf : "

		Goto ResumeNext

	End If

	If Not db1 Is Nothing Then

		Set ua = New NotesUserActivity(db1)

		If docB.MiddleInitial(0)="" Then 

			longname=docB.Firstname(0) +" " + docB.LastName(0)

		Else

			longname=docB.Firstname(0) + " " + docB.MiddleInitial(0) + " " + docB.Lastname(0)

		End If

		If docB.Firstname(0)="" Then

			longname=docB.LastName(0)

		End If

		For iCounter = 1 To ua.UserActivityCount

			Set uae = ua.GetNthUserActivityEntry(iCounter)

			lenname=Len(longname)

			If (Left$( uae.Username, lenname)=Left$(longname$,lenname) )Then  

				If test=0 Then

					Print #filenum%, "Last Accessed:"+ uae.Time +"  " + uae.Username      + " "    

					test=1

					Call docB.replaceitemvalue ("FirstAccess", ua.First)     

					Call docB.replaceitemvalue ("LastAccess", uae.Time)     

					Call docB.replaceitemvalue ("DSTProc", "Yes") 

					Call docB.save(True,True)

				End If 

			End If

			If  (Mid$( uae.Username, 4,lenname)=Left$(longname$,lenname) )Then  

				If test=0 Then

					Print #filenum%, "Last Accessed:"+ uae.Time +"  " + uae.Username      + " "    

					test=1

					Call docB.replaceitemvalue ("FirstAccess", ua.First)     

					Call docB.replaceitemvalue ("LastAccess", uae.Time)     

					Call docB.replaceitemvalue ("DSTProc", "Yes") 

					Call docB.save(True,True)

				End If 

			End If

			

			

               ' Print #filenum%,"(" + Cstr(iCounter) + ") " + uae.Time + " " + uae.UserName + " " + "Reads:" + Cstr(uae.Reads) + " Writes:" + Cstr(uae.Writes)

			

		Next iCounter

		If test=0 Then

			Print #filenum%, "No Activity since "+ ua.First

			Call docB.replaceitemvalue ("FirstAccess", ua.First)     

			Call docB.replaceitemvalue ("LastAccess", "No Activity")     

			Call docB.save(True,True)

		End If

	End If

ResumeNext:

	Set docB = coll.getnextdocument(docA) 

	Set docA = docB

	

Wend

Close filenum%

Exit Sub

Errortrap:

Print #filenum%,"Error opening mail file: " + docB.Firstname(0) +" " + docB.LastName(0) +":" + + docB.MailFile(0) + ".nsf : " + docB.MailServer(0)

End Sub

CLASSUserActivity


Option Public

Option Explicit

Const MAXALPHATIMEDATE = 80

Type TIMEDATE

Innard1 As Long

Innard2 As Long

End Type

Type DBACTIVITY

First As TIMEDATE

Last As TIMEDATE

Uses As Long

Reads As Long

Writes As Long

PrevDayUses As Long

PrevDayReads As Long

PrevDayWrites As Long

PrevWeekUses As Long

PrevWeekReads As Long

PrevWeekWrites As Long

PrevMonthUses As Long

PrevMonthReads As Long

PrevMonthWrites As Long

End Type

Type DBACTIVITY_ENTRY

Time As TIMEDATE

Reads As Integer

Writes As Integer

UserNameOffset As Long

End Type

Declare Function W32_NSFDbOpen Lib “nnotes.dll” Alias “NSFDbOpen” ( Byval dbName As String, hDb As Long) As Integer

Declare Function W32_NSFDbClose Lib “nnotes.dll” Alias “NSFDbClose” ( Byval hDb As Long) As Integer

Declare Function W32_NSFDbGetUserActivity Lib “nnotes.dll” Alias “NSFDbGetUserActivity” ( Byval hDB As Long, Byval flags As Long, retDbActivity As DBActivity, rethUserInfo As Long, retUserCount As Long) As Integer

Declare Function W32_OSLockObject Lib “nnotes.dll” Alias “OSLockObject” ( Byval handle) As Long

Declare Sub OSUnlockObject Lib “NNOTES.DLL” Alias “OSUnlockObject” (Byval handle)

Declare Sub W32_OSMemFree Lib “NNOTES.DLL” Alias “OSMemFree” (Byval handle)

Declare Sub CopyMemory Lib “KERNEL32” Alias “RtlMoveMemory” ( hpvDest As Any, Byval hpvSource As Long, Byval cbCopy As Long)

Declare Sub CopyMemoryString Lib “KERNEL32” Alias “RtlMoveMemory” ( Byval hpvDest As String, Byval hpvSource As Long, Byval cbCopy As Long)

Declare Sub ConvertTIMEDATEToText Lib “NNOTES.DLL” Alias “ConvertTIMEDATEToText” (Byval IntlFormat As Long,Byval TextFormat As Long, actTIMEDATE As TIMEDATE, Byval retTextBuffer As String,Byval TextBufferLength As Integer,retTextLength As Integer)

Class NotesUserActivityEntry

Public UserName As String

Public Reads As Long

Public Writes As Long

Public Time As String

End Class

Class NotesUserActivity

Private hDb As Long

Private pDbActivity As DBACTIVITY

Private rethUserInfo As Long

Private retUserCount As Long

Private prvdb As NotesDatabase

Private flgHasActivity As Integer



Sub Delete

	If Me.flgHasActivity Then Call W32_OSMemFree(rethUserInfo)

	If hDb <> 0 Then Call W32_NSFDbClose(hDb)   

End Sub



Sub New (inpNotesDatabase As NotesDatabase)

	

	Dim sDatabase As String

	Dim rc As Integer     

	

	Me.flgHasActivity = False

	

      'Get a valid NotesDatabase to the specified database         

	If inpNotesDatabase Is Nothing Then 

		Error 14101, "NotesUserActivity: Database Object is invalid"

		Exit Sub

	End If

	

	Set prvdb = New NotesDatabase(inpNotesDatabase.Server, inpNotesDatabase.FilePath)

	

	If prvdb.Server = "" Then

		sdatabase = prvdb.filepath

	Else

		sdatabase = prvdb.server + "!!" + prvdb.filepath

	End If

	

      'Open the target database

	rc = W32_NSFDbOpen(sDatabase,Me.hDb)

	If rc <> 0 Then

		Me.flgHasActivity = False

	End If

	

      'Get the Summary User information

	rc = W32_NSFDbGetUserActivity(Me.hDb, &h0, Me.pDbActivity, Me.rethUserInfo, Me.retUserCount)

	If rc <> 0 Then

		Me.flgHasActivity = False

	End If      

	Me.flgHasActivity = True

End Sub 



 'Global Times

Public Function First As String

	First = ConvertTIMEtoText(pDbActivity.First)     

End Function

Public Function Last As String

	Last = ConvertTIMEtoText(pDbActivity.Last)     

End Function



 'Total summary

Public Function Uses As Long

	Uses = pDbActivity.Uses  

End Function

Public Function Reads As Long

	Reads = pDbActivity.Reads          

End Function

Public Function Writes As Long

	Writes = pDbActivity.Writes

End Function



 'Day summary

Public Function PrevDayUses As Long

	PrevDayUses = pDbActivity.PrevDayUses     

End Function

Public Function PrevDayReads As Long

	PrevDayReads = pDbActivity.PrevDayReads     

End Function

Public Function PrevDayWrites As Long

	PrevDayWrites = pDbActivity.PrevDayReads

End Function



 'Week summary

Public Function PrevWeekUses As Long

	PrevWeekUses = pDbActivity.PrevWeekUses          

End Function

Public Function PrevWeekReads As Long

	PrevWeekReads = pDbActivity.PrevWeekReads

End Function

Public Function PrevWeekWrites As Long

	PrevWeekWrites= pDbActivity.PrevWeekWrites

End Function



 'Month summary

Public Function PrevMonthUses As Long

	PrevMonthUses = pDbActivity.PrevMonthUses               

End Function

Public Function PrevMonthReads As Long

	PrevMonthReads = pDbActivity.PrevMonthReads     

End Function

Public Function PrevMonthWrites As Long

	PrevMonthWrites = pDbActivity.PrevMonthWrites

End Function



Public Function UserActivityCount As Long

	UserActivityCount = retUserCount

End Function



Public Function HasUserActivity As Integer

	HasUserActivity = Me.flgHasActivity

End Function



Public Function Parent As NotesDatabase

	Set Parent = prvdb

End Function



Public Function GetNthUserActivityEntry(inpEntry As Long) As NotesUserActivityEntry

	Dim puActivity As Long

	Dim lEntry As Long

	Dim puActivityEntry As DBACTIVITY_ENTRY

	Dim StructureOffset As Long

	Dim UsernameOffset As Long

	Dim spUsername As String * 256

	Dim sUsername As String

	Dim nuae As New NotesUserActivityEntry

	

	lEntry = inpEntry - 1

	

	If Not Me.flgHasActivity Then Error 14104, "NotesUserActivity: No activity available"

	

	If lEntry > Me.retUserCount Or lEntry < 0 Then

		Error 14103, "NotesUserActivity: Subscript out of range."

	End If

	

      'Lock the structure get the required entry

	puActivity = W32_OSLockObject(Me.rethUserInfo)

	StructureOffset = puActivity + (Lenb(puActivityEntry) * lEntry)

	Call CopyMemory (puActivityEntry, StructureOffset, Len(puActivityEntry))

	

      'Load the User name for the Activity Structure

	UsernameOffset = puActivity + puActivityEntry.UserNameOffset

	spUsername = Space(256)

	Call CopyMemoryString(spUsername, UsernameOffset,Lenb(spUsername))

	sUserName = Left(spUsername, Instr(spUsername, Chr(0)) - 1)

	

	With nuae

		.UserName = sUserName

		.Reads = puActivityEntry.Reads

		.Writes = puActivityEntry.Writes

		.Time = ConvertTIMEtoText(puActivityEntry.Time)

	End With

	

	Call OSUnlockObject(rethUserInfo)

	

	Set GetNthUserActivityEntry = nuae

	

End Function

End Class

Function ConvertTIMEtoText(TIMESTRUCT As TIMEDATE) As String

Dim spTime As String * MAXALPHATIMEDATE

Dim retLength As Integer



spTime = Space(MAXALPHATIMEDATE)

Call ConvertTIMEDATEToText (&h0,&h0, TIMESTRUCT, spTime,MAXALPHATIMEDATE,retLength)

ConvertTIMEtoText = Left(spTime,retLength)

End Function

Subject: Scheduled Agent to determine when user last accessed mail file stops too soon

We had the same problem. The Problem is the CLASSUserActivity Library. It causes some memory leak and falls over. We did a workaround by using the Usage documents in the log.nsf. Unfortunately, the Usage documents are stored by User, and the databases that they have accessed. We had to build another database that had an agent which re-organised the information by Database. That actually worked quite well.

Subject: Scheduled Agent to determine when user last accessed mail file stops too soon

Have you checked out sandbox:

http://www-10.lotus.com/ldd/sandbox.nsf/ecc552f1ab6e46e4852568a90055c4cd/e0ff0464768be1a085256b37004f25b6?OpenDocument

Agents generally stop running when they exceed configured time, or run out of memory.

I had one that I had to put a timer on, exit when the time reached the configured time, and then start up where it left off in order to finish it’s processing.

It’s also possible to run through the server log by user thread to collect the same stats.

Good luck,

Marilyn

Subject: SOLUTION: Scheduled Agent to determine when user last accessed mail file stops too soon

See my post here:https://www-10.lotus.com/ldd/nd6forum.nsf/ShowMyTopicsAllThreadedweb/f7aaccba75ce0c70852570d60064bcbc?OpenDocument

Subject: Memory Leak - Fixed

Agent requires 1 extra line of code - see solution

http://www-10.lotus.com/ldd/nd6forum.nsf/55c38d716d632d9b8525689b005ba1c0/4f67561db8fd67f48525724a0041b336?OpenDocument