Autor Thema: Replication Settings von großen Datenbanken per C API auslesen  (Gelesen 2786 mal)

Offline Johnson

  • Senior Mitglied
  • ****
  • Beiträge: 258
  • Geschlecht: Männlich
Hallo Notesianer,

ich bräuchte wohl mal einen richtigen Stupser in die richtige Richtung:

Ich habe einen Agenten, der einige Eigenschaften der Datenbanken unserer Server ausliest. U.a. werde auch die Repliziereinstellungen ausgelesen.

Dazu habe ich eine Funktion, die sich mittels der API die Replication Forumlas holt. Dies kann u.U. ewig dauern. Je nach Größe der Datenbank. Hier mal der Code eines Testagenten:

Code
Option Public
Option Declare

Declare Private Function apiIDDestroyTable Lib "nnotes.dll" Alias "IDDestroyTable" (Byval lng_tablehandle As Long) As Integer
Declare Private Function apiIDEntries Lib "nnotes.dll" Alias "IDEntries" (Byval lng_tablehandle As Long) As Integer
Declare Private Function apiIDScan Lib "nnotes.dll" Alias "IDScan" (Byval lng_tablehandle As Long, Byval bln_isfirst As Integer, lng_id As Long) As Integer
Declare Private Function apiNSFDbClose Lib "nnotes.dll" Alias "NSFDbClose" (Byval lng_dbhandle As Long) As Integer
Declare Private Function apiNSFDbGetModifiedNoteTable Lib "nnotes.dll" Alias "NSFDbGetModifiedNoteTable"(Byval lng_hdb As Long, Byval int_class As Integer, Byval dbl_startdate As Double, dbl_enddate As Double, lng_rettablehandle As Long) As Integer
Declare Private Function apiNSFDbOpen Lib "nnotes.dll" Alias "NSFDbOpen" (Byval str_netfilepath As String, lng_dbhandle As Long) As Integer
Declare Private Function apiOSPathNetConstruct Lib "nnotes.dll" Alias "OSPathNetConstruct" (Byval lng_port As Long, Byval str_server As String, Byval str_filepath As String, Byval str_netfilepath As String) As Integer
Declare Private Sub apiTimeConstant Lib "nnotes.dll" (Byval lng_timeconstanttype As Long, dbl_datetime As Double)

Sub Initialize
	
	Dim s As New NotesSession
	Dim db As NotesDatabase
	
	Set db = s.GetDatabase("", "log.nsf")
	
	Call GetReplicationFormulas(db)
	
End Sub

Function GetNetFilePath(str_server As String, str_filepath As String) As String
	
	Dim lng_apiresult As Long
	Dim str_netfilepath As String
	
	
' ### get network file path ###
	
	str_netfilepath = Space(256)
	lng_apiresult = apiOSPathNetConstruct(0, str_server, str_filepath, str_netfilepath)
	If Not(lng_apiresult = 0) Then
		Goto terminate
	End If
	If Instr(str_netfilepath, Chr(0)) > 0 Then
		str_netfilepath = Strleft(str_netfilepath, Chr(0))
	End If
	
	
' ### return value ###
	
	GetNetFilePath = Trim(str_netfilepath)
	
	
' ### terminate ###
	
terminate:
	Exit Function
	
End Function

Function GetReplicationFormulas(db_source As NotesDatabase) As NotesDocumentCollection
	
	Dim dbl_enddate As Double
	Dim dbl_startdate As Double
	Dim dc As NotesDocumentCollection
	Dim doc As NotesDocument
	Dim lng_entries As Long
	Dim lng_entry As Long
	Dim lng_hdb As Long
	Dim lng_hidtable As Long
	Dim lng_noteid As Long
	Dim int_apiresult As Integer
	Dim str_networkfilepath As String
	
	Const TIMEDATE_MINIMUM = 0
	Const NOTE_CLASS_REPLFORMULA = &H0800
	
	
' ### open database ###
	
	str_networkfilepath = GetNetFilePath(db_source.Server, db_source.FilePath)
	If str_networkfilepath = "" Then Goto terminate
	
	int_apiresult = apiNSFDbOpen(str_networkfilepath, lng_hdb)
	If Not(int_apiresult = 0) Then Goto terminate
	
	
' ### get table of note ids containing the replication formulas ###
	
	Call apiTimeConstant(TIMEDATE_MINIMUM, dbl_startdate)
	int_apiresult = apiNSFDbGetModifiedNoteTable(lng_hdb, NOTE_CLASS_REPLFORMULA, dbl_startdate, dbl_enddate, lng_hidtable)
	If Not(int_apiresult = 0) Then Goto closedb
	
' validation
	lng_entries = apiIDEntries(lng_hidtable)
	If lng_entries = 0 Then Goto destroytable
	
	
' ### get note ids of the unread documents an build collection ###
	
	For lng_entry = 1 To lng_entries
		If apiIDScan(lng_hidtable, (lng_entry = 1), lng_noteid) > 0 Then
			Set doc = db_source.GetDocumentByID(Hex$(lng_noteid))
			If Not(doc Is Nothing) Then
				Call dc.AddDocument(doc)
			End If
		End If
	Next lng_entry
	
	
' ### release id table memory ###
	
destroytable:
	int_apiresult = apiIDDestroyTable(lng_hidtable)
	If Not(int_apiresult = 0) Then Goto closedb
	
	
' ### close database ###
	
closedb:
	Call apiNSFDbClose(lng_hdb)
	
	
' ### return value ###
	
	If dc.Count > 0 Then Set GetReplicationFormulas = dc
	
	
' ### terminate ###
	
terminate:
	Exit Function
	
End Function


So. Der TIMEDATE_MINIMUM Timestamp wird der NSFDbGetModifiedNoteTable übergeben. Beim Suchen nach "normalen" Dokumente (NOTE_CLASS_DOCUMENT statt NOTE_CLASS_REPLFORMULA) geht das Ruckzuck binnen Millisekunden. Selbst bei megagroßen Datenbanken. Nur mit den Replication Formulas scheint das nicht zu funktionieren.

Mach ich da was falsch?

Wie geht Notes hier vor? Denn wenn ich bei diesen großen Datenbanken die Repliziereinstellungen aufrufe, öffnen diese sich ebenfalls recht schnell.


Gruß
Johnson
Gruß
Johnson

Offline Johnson

  • Senior Mitglied
  • ****
  • Beiträge: 258
  • Geschlecht: Männlich
Ups... Durch die Umstellung zu einem Testagenten hat sich ein kleiner Fehler eingeschlichen. Hier nochmal ein funktionierender Testagent:

Code
Option Public
Option Declare

Declare Private Function apiIDDestroyTable Lib "nnotes.dll" Alias "IDDestroyTable" (Byval lng_tablehandle As Long) As Integer
Declare Private Function apiIDEntries Lib "nnotes.dll" Alias "IDEntries" (Byval lng_tablehandle As Long) As Integer
Declare Private Function apiIDScan Lib "nnotes.dll" Alias "IDScan" (Byval lng_tablehandle As Long, Byval bln_isfirst As Integer, lng_id As Long) As Integer
Declare Private Function apiNSFDbClose Lib "nnotes.dll" Alias "NSFDbClose" (Byval lng_dbhandle As Long) As Integer
Declare Private Function apiNSFDbGetModifiedNoteTable Lib "nnotes.dll" Alias "NSFDbGetModifiedNoteTable"(Byval lng_hdb As Long, Byval int_class As Integer, Byval dbl_startdate As Double, dbl_enddate As Double, lng_rettablehandle As Long) As Integer
Declare Private Function apiNSFDbOpen Lib "nnotes.dll" Alias "NSFDbOpen" (Byval str_netfilepath As String, lng_dbhandle As Long) As Integer
Declare Private Function apiOSPathNetConstruct Lib "nnotes.dll" Alias "OSPathNetConstruct" (Byval lng_port As Long, Byval str_server As String, Byval str_filepath As String, Byval str_netfilepath As String) As Integer
Declare Private Sub apiTimeConstant Lib "nnotes.dll" Alias "TimeConstant" (Byval lng_timeconstanttype As Long, dbl_datetime As Double)

Sub Initialize
	
	Dim s As New NotesSession
	Dim db As NotesDatabase
	
	Set db = s.GetDatabase("", "log.nsf")
	
	Call GetReplicationFormulas(db)
	
End Sub

Function GetNetFilePath(str_server As String, str_filepath As String) As String
	
	Dim lng_apiresult As Long
	Dim str_netfilepath As String
	
	
' ### get network file path ###
	
	str_netfilepath = Space(256)
	lng_apiresult = apiOSPathNetConstruct(0, str_server, str_filepath, str_netfilepath)
	If Not(lng_apiresult = 0) Then
		Goto terminate
	End If
	If Instr(str_netfilepath, Chr(0)) > 0 Then
		str_netfilepath = Strleft(str_netfilepath, Chr(0))
	End If
	
	
' ### return value ###
	
	GetNetFilePath = Trim(str_netfilepath)
	
	
' ### terminate ###
	
terminate:
	Exit Function
	
End Function

Function GetReplicationFormulas(db_source As NotesDatabase) As NotesDocumentCollection
	
	Dim dbl_enddate As Double
	Dim dbl_startdate As Double
	Dim dc As NotesDocumentCollection
	Dim doc As NotesDocument
	Dim lng_entries As Long
	Dim lng_entry As Long
	Dim lng_hdb As Long
	Dim lng_hidtable As Long
	Dim lng_noteid As Long
	Dim int_apiresult As Integer
	Dim str_networkfilepath As String
	
	Const TIMEDATE_MINIMUM = 0
	Const NOTE_CLASS_REPLFORMULA = &H0800
	
	
' ### open database ###
	
	str_networkfilepath = GetNetFilePath(db_source.Server, db_source.FilePath)
	If str_networkfilepath = "" Then Goto terminate
	
	int_apiresult = apiNSFDbOpen(str_networkfilepath, lng_hdb)
	If Not(int_apiresult = 0) Then Goto terminate
	
	
' ### get table of note ids containing the replication formulas ###
	
	Call apiTimeConstant(TIMEDATE_MINIMUM, dbl_startdate)
	int_apiresult = apiNSFDbGetModifiedNoteTable(lng_hdb, NOTE_CLASS_REPLFORMULA, dbl_startdate, dbl_enddate, lng_hidtable)
	If Not(int_apiresult = 0) Then Goto closedb
	
' validation
	lng_entries = apiIDEntries(lng_hidtable)
	If lng_entries = 0 Then Goto destroytable
	
	
' ### get note ids of the unread documents an build collection ###
	
	Set dc = db_source.Search({}, Nothing, 0)
	For lng_entry = 1 To lng_entries
		If apiIDScan(lng_hidtable, (lng_entry = 1), lng_noteid) > 0 Then
			Set doc = db_source.GetDocumentByID(Hex$(lng_noteid))
			If Not(doc Is Nothing) Then
				Call dc.AddDocument(doc)
			End If
		End If
	Next lng_entry
	
	
' ### release id table memory ###
	
destroytable:
	int_apiresult = apiIDDestroyTable(lng_hidtable)
	If Not(int_apiresult = 0) Then Goto closedb
	
	
' ### close database ###
	
closedb:
	Call apiNSFDbClose(lng_hdb)
	
	
' ### return value ###
	
	If Not(dc Is Nothing) Then
		If dc.Count > 0 Then Set GetReplicationFormulas = dc
	End If
	
	
' ### terminate ###
	
terminate:
	Exit Function
	
End Function

Zum Testen einfach im Initialize eine andere Datenbank angeben, da die Replication Forumlas nicht in jeder Datenbank vorhanden sind. So wie es aussieht sie die erst vorhanden, wenn in den Replication Settings unter Advanced einmal was geändert und abgespeichert wurde...

Gruß
Johnson

Offline eknori

  • @Notes Preisträger
  • Moderator
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 11.728
  • Geschlecht: Männlich
Warum nimmst du nicht LS? NotesReplication class + NotesReplicationEntry class gibt es seit Version 6
Egal wie tief man die Messlatte für den menschlichen Verstand auch ansetzt: jeden Tag kommt jemand und marschiert erhobenen Hauptes drunter her!

Offline Johnson

  • Senior Mitglied
  • ****
  • Beiträge: 258
  • Geschlecht: Männlich
Es ging darum alle vorhandenen Konfigurationen auszulesen und so einen Überblick zu verschaffen.

Die Klasse NotesReplication hat richtigerweise die Funktion GetEntry. Bei dieser Funktion müssen jedoch Quell- und Zielserver angegeben werden. Bei über 100 Servern, die bei uns gescannt werden und den daraus entstehenden Kombinationen (?)...
Gruß
Johnson

Offline Johnson

  • Senior Mitglied
  • ****
  • Beiträge: 258
  • Geschlecht: Männlich
So. Nach einigen NSDs und Verlussten in den Reihen meiner Nervenzellen ist es mir gelungen das Performanceproblem zu lösen.

Die Testdatenbank gab mit der obigen Funktionsversion erst nach ca. 1 Minute die Replication Formulas zurück. Vermutlich liegt es daran, dass diese Funktion eigentlich zum Identifizieren von geänderten Dokumenten dient.
Die nachvolgenden Funktionsversion rückt die Replication Formulas der Testdatenbank bereits nach 0,02 Sekunden raus.  :o Der König ist tot, lang lebe der König!  ;D

Code
Option Public
Option Declare

Private Const MAXTUMBLERLEVELS = 32
Private Const NAVIGATE_CURRENT = 0
Private Const NAVIGATE_NEXT = 1
Private Const READ_MASK_NOTEID = 1&
Private Const READ_MASK_NOTECLASS = 4&
Private Const NOTE_CLASS_REPLFORMULA = 2048&
Private Const NOTE_ID_SPECIAL = &HFFFF0000&
Private Const NOTE_CLASS_DESIGN = &H0020&

Private Const SIGNAL_MORE_TO_DO = &H0020
Private Const SIGNAL_DEFN_ITEM_MODIFIED = &H0001
Private Const SIGNAL_VIEW_ITEM_MODIFIED = &H0002
Private Const SIGNAL_INDEX_MODIFIED = &H0004
Private Const SIGNAL_UNREADLIST_MODIFIED = &H0008
Private Const SIGNAL_DATABASE_MODIFIED = &H0010
Private Const SIGNAL_VIEW_TIME_RELATIVE = &H0040
Private Const SIGNAL_NOT_SUPPORTED = &H0080
Private Const SIGNAL_ANY_CONFLICT = SIGNAL_DEFN_ITEM_MODIFIED Or SIGNAL_VIEW_ITEM_MODIFIED Or SIGNAL_INDEX_MODIFIED Or SIGNAL_UNREADLIST_MODIFIED Or SIGNAL_DATABASE_MODIFIED
Private Const SIGNAL_ANY_NONDATA_CONFLICT = SIGNAL_DEFN_ITEM_MODIFIED Or SIGNAL_VIEW_ITEM_MODIFIED Or SIGNAL_INDEX_MODIFIED Or SIGNAL_UNREADLIST_MODIFIED

Private Type COLLECTIONPOSITION
	Level As Integer
	MinLevel As String * 1
	MaxLevel As String * 1
	Tumbler(0 To MAXTUMBLERLEVELS - 1) As Long
End Type

Private Type DESIGNOBJECTS
	NoteID As Long
	NoteClass As Integer
End Type

Declare Private Function apiIDEntries Lib "nnotes.dll" Alias "IDEntries" (Byval lng_tablehandle As Long) As Integer
Declare Private Function apiNIFCloseCollection Lib "nnotes.dll" Alias "NIFCloseCollection" ( Byval hCol As Long) As Integer
Declare Private Function apiNSFDbClose Lib "nnotes.dll" Alias "NSFDbClose" (Byval lng_dbhandle As Long) As Integer
Declare Private Function apiNSFDbOpen Lib "nnotes.dll" Alias "NSFDbOpen" (Byval str_netfilepath As String, lng_dbhandle As Long) As Integer
Declare Private Function apiNIFOpenCollection Lib "nnotes.dll" Alias "NIFOpenCollection" (Byval lng_viewdbhandle As Long, Byval lng_datadbhandle As Long, Byval lng_viewnoteid As Long, _
Byval int_openflags As Integer, Byval lng_unreadlisthandle As Long, rethCollection As Long, Byval rethViewNote As Long, Byval retViewUNID As Long, _
Byval rethCollapsedList As Long, Byval rethSelectedList As Long) As Integer
Declare Private Function apiNIFReadEntries Lib "nnotes.dll" Alias "NIFReadEntries" (Byval lng_collectionhandle As Long, cp_index As COLLECTIONPOSITION, _
Byval int_skipnavigator As Integer, Byval lng_skipcount As Long, Byval ReturnNavigator As Integer, _
Byval lng_retcount As Long, Byval lng_retmask As Long, lng_retbuffer As Long, int_retbufferlength As Integer, lng_skippedcount As Long, lng_returncount As Long, int_signal As Integer) As Integer
Declare Private Function apiNIFUpdateCollection Lib "nnotes.dll" Alias "NIFUpdateCollection" (Byval lng_collectionhandle As Long) As Integer
Declare Private Function apiOSLockObject Lib "nnotes.dll" Alias "OSLockObject" (Byval handle As Long) As Long
Declare Private Function apiOSPathNetConstruct Lib "nnotes.dll" Alias "OSPathNetConstruct" (Byval lng_port As Long, Byval str_server As String, Byval str_filepath As String, Byval str_netfilepath As String) As Integer
Declare Private Function apiOSUnlockObject Lib "nnotes.dll" Alias "OSUnlockObject" (Byval Handle As Long) As Integer

Declare Private Sub apiMoveMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, Byval Length As Long)

Sub Initialize
	
	Dim s As New NotesSession
	Dim db As NotesDatabase
	Dim dbl_start As Double
	Dim dbl_end As Double
	
	Set db = s.GetDatabase("sedcd109.wk.dcx.com", "dart\096\dev\sclaren\bhbtest.nsf")
	
	Set db = s.CurrentDatabase
	dbl_start = Timer
	Call FindReplicationFormulas(db)
	dbl_end = Timer
	Print "FindReplicationFormulas: " & Round(dbl_end - dbl_start, 2)
	
End Sub

Function GetNetFilePath(str_server As String, str_filepath As String) As String
	
	Dim lng_apiresult As Long
	Dim str_netfilepath As String
	
	
' ### get network file path ###
	
	str_netfilepath = Space(256)
	lng_apiresult = apiOSPathNetConstruct(0, str_server, str_filepath, str_netfilepath)
	If Not(lng_apiresult = 0) Then
		Goto terminate
	End If
	If Instr(str_netfilepath, Chr(0)) > 0 Then
		str_netfilepath = Strleft(str_netfilepath, Chr(0))
	End If
	
	
' ### return value ###
	
	GetNetFilePath = Trim(str_netfilepath)
	
	
' ### terminate ###
	
terminate:
	Exit Function
	
End Function

Function FindReplicationFormulas(db_source As NotesDatabase) As NotesDocumentCollection
	
	Dim cp_index As COLLECTIONPOSITION
	Dim dc As NotesDocumentCollection
	Dim doc As NotesDocument
	Dim int_apiresult As Integer
	Dim int_bufferlength As Integer
	Dim int_counter As Integer
	Dim int_signal As Integer
	Dim lng_bufferaddress As Long
	Dim lng_bufferhandleaddress As Long
	Dim lng_hcollection As Long
	Dim lng_hdb As Long
	Dim lng_htable As Long
	Dim lng_returnedcount As Long
	Dim lng_skippedcount As Long
	Dim str_networkfilepath As String
	Dim do_noteinfo As DesignObjects
	
	
' ### initialize ###
	
	If db_source Is Nothing Then Goto terminate
	
	
' ### open database ###
	
	str_networkfilepath = GetNetFilePath(db_source.Server, db_source.FilePath)
	If str_networkfilepath = "" Then Goto terminate
	
	int_apiresult = apiNSFDbOpen(str_networkfilepath, lng_hdb)
	If Not(int_apiresult = 0) Then Goto terminate
	
	
' ### open collection ###
	
	int_apiresult = apiNIFOpenCollection(lng_hdb, lng_hdb, (NOTE_CLASS_DESIGN Or NOTE_ID_SPECIAL), 0, 0&, lng_hcollection, 0, 0&, 0&, 0&)
	If Not(int_apiresult = 0) Then Goto closecollection
	If lng_hcollection = 0 Then Goto closedb
	
' ### read entries ###
	
' initialize the position in the collection
	cp_index.Level = 0
	cp_index.Tumbler(0) = 0
	
' do while there is anything to read
	Do
		
		' read all entries and load the note id and the note class into buffer
		Do
			
			int_apiresult = apiNIFReadEntries(lng_hcollection, cp_index, NAVIGATE_NEXT, 1&, NAVIGATE_NEXT, -1&, (READ_MASK_NOTEID Or READ_MASK_NOTECLASS), _
			lng_bufferhandleaddress, int_bufferlength, lng_skippedcount, lng_returnedcount, int_signal)
			If Not(int_apiresult = 0) Goto closecollection
			
			' update collection if the collection was changed since last read
			If (int_signal And SIGNAL_ANY_CONFLICT) = SIGNAL_ANY_CONFLICT Then
				int_apiresult = apiNIFUpdateCollection(lng_hcollection)
				If Not(int_apiresult = 0) Then Goto closecollection
			End If
			
		Loop While ((int_signal And SIGNAL_ANY_CONFLICT) = SIGNAL_ANY_CONFLICT)
		If lng_bufferhandleaddress = 0 Then Goto closecollection
		
		' lock buffer and return the address of the buffer
		lng_bufferaddress = apiOSLockObject(lng_bufferhandleaddress)
		
		' get the design documents
		For int_counter = 1 To lng_returnedcount
			
			' copy the information of one design document into the design object structure
			' long 4 bytes + integer 2 bytes
			Call apiMoveMemory(do_noteinfo, Byval lng_bufferaddress + ((int_counter - 1) * 6), Byval 6)
			
			' add document to document collection if a replication formula was found
			If do_noteinfo.NoteClass = NOTE_CLASS_REPLFORMULA Then
				If dc Is Nothing Then Set dc = db_source.Search({}, Nothing, 0)
				Set doc = db_source.GetDocumentByID(Hex$(do_noteinfo.NoteID))
				If Not(doc Is Nothing) Then Call dc.AddDocument(doc)
			End If
			
		Next int_counter
		
		' unlock buffer
		Call apiOSUnlockObject(lng_bufferhandleaddress)
		
	Loop While ((int_signal And SIGNAL_MORE_TO_DO) = SIGNAL_MORE_TO_DO)
	
' ### close collection ###
	
closecollection:
	int_apiresult = apiNIFCloseCollection(lng_hcollection)
	If Not(int_apiresult = 0) Then Goto closedb
	
	
' ### close database ###
	
closedb:
	Call apiNSFDbClose(lng_hdb)
	
	
' ### return value ###
	
	If Not(dc Is Nothing) Then Set FindReplicationFormulas = dc
	
	
' ### terminate ###
	
terminate:
	Exit Function
	
End Function
« Letzte Änderung: 16.04.10 - 12:41:44 von Johnson »
Gruß
Johnson

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz