Performances renommage utilisateurs Documentum
L'article Renommer Utilisateur a permis de décrine le fonctionnement du job pour renommer un utilisateur sous Documentum. Dans le cadre d'une intégration, un client avait beaucoup de modification de noms d'utilisateur, sur une docbase volumineuse, entraînant un temps de traitement supérieur à la journée. Une partie de amélioration de performances a été réalisée sur l'étude de cette méthode et son optimisation. Ce n'était certe pas les gains les plus importants, mais cela était assez spectaculaire pris individuellement, allant jusqu'à un facteur 10.
Votre avis
Nobody voted on this yet
|
|
Analyse version 6.7 SP1
Pour rappel, le job dm_UserRename
exécute la méthode serveur de même nom, afin de traiter l'ensemble de demandes de renommage modélisées dans des instances de dm_job_request
. La valeur de l'attribut method_veb
est .\dmbasic -f..\install\admin\userrename.ebs -eUserRename
permettant d'identifier:
Paramètre | Valeur |
---|---|
Emplacement code source. | ..\install\admin\userrename.ebs par rapport aux répertoire d'exécution.
|
Point d'entrée de la méthode. | fonction UserRename .
|
Etant un code en DocBasic
, il est très facile de l'étudier et de le modifier.
Exécution
Le traitement débute par l'exécution de la fonction UserRename
, dont le code est le suivant:
Sub UserRename(dummy_arg01 As String, DocBase As String, _
dummy_arg02 As String, UserName As String, _
dummy_arg03 As String, JobID As String, _
dummy_arg04 As String, MethodTraceLevel As String)
Dim dmclTracePath As String, QueryStr As String, Unused As String, DmValue As String
Dim DmPriority As Integer, MethArgValues As Integer, ret As Integer
Dim IndividualLogPath As String, DQL_IndividualLogPath As String
IndividualLog = false
DocbaseName = DocBase
SuperUserName = UserName
SuperUserPswd = ""
JobName = ""
ReportOnly = true
UnlockLckObj = false
Call DmConnect()
JobName = dmAPIGet("get,c," & JobID & ",object_name")
JobLogDocName = "UserRename"
dmclTracePath = dmAPIGet("get,a,apiconfig,r_trace_file")
Call MakeResultDoc(dmclTracePath$, MethodTraceLevel)
MethArgValues = dmAPIGet("values,c," & JobID & ",method_arguments")
DmPriority = 0
If(MethArgValues > 0) Then
DmPriority = dmAPIGet("get,c," & JobID & ",method_arguments[0]")
ret = dmAPIExec("remove,c," & JobID & ",method_arguments[0]")
ret = dmAPIExec("save,c," & JobID)
If ret = 0 Then
Call DmPrint("Could not modify and save job " & JobName & _
".", "fatal")
End If
End If
ret = dmAPISet("append,c,sessionconfig,application_code", "dm_userrename")
If ret = 0 Then
Call DmPrint("Could not append session application_code", "fatal")
End If
QueryStr = "id,c,dm_job_request where job_name = '" & JobName & _
"' and request_completed = false and priority >= " & _
DmPriority & " order by r_object_id"
RequestDocId = dmAPIGet(QueryStr)
If(RequestDocId = "") Then
Call DmPrint("No users are scheduled for rename." , "information")
Unused = dmAPIGet("getmessage,c")
Else
While(RequestDocId <> "")
DmValue = DmGetRenameOptions(RequestDocId)
If(DmValue = 0) Then
Call DmPrint("Could not run job for dm_job_request " & _
RequestDocId & ", scheduled to rename user " & _
OldUserName & " to " & NewUserName & ".", "information")
Else
IndividualLogPath = "tempUser" & RequestDocId & ".txt"
If FileExists(IndividualLogPath) Then Kill IndividualLogPath
Open IndividualLogPath For Output As #3
IndividualLog = true
Call DmUserRename(MethodTraceLevel)
close #3
IndividualLog = false
ret = dmAPIExec("setfile,c," & RequestDocId & _
"," & IndividualLogPath & ",text")
ret = dmAPIExec("save,c," & RequestDocId)
If ret = 0 Then
Call DmPrint("Could not save log document for the " & _
"rename operation (user " & OldUserName & " to " & _
NewUserName & ").", "error")
End If
If FileExists(IndividualLogPath) Then Kill IndividualLogPath
End If
RequestDocId = dmAPIGet(QueryStr)
Wend
Unused$ = dmAPIGet("getmessage,c")
End If
Call SaveResultDoc(dmclTracePath$, MethodTraceLevel, JobName)
ret = SetJobStatus(JobID, "User Rename Completed At " & dmNow(date & " " & time$))
ret = dmAPIExec("disconnect,c")
End Sub
Cette fonction va permettre de récupérer les informations, mettre à jour le statut du job et enfin de sauvegarder les traces, principe qui se retrouve dans une grande majorité des méthodes serveurs d'administration de Documentum.
Lecture instructions
L'apppel à la fonction DmGetRenameOptions
va permettre de stocker temporairement les paramètres de renommage, instance de dm_job_request
, dans des variables globales de la méthode. Sa lecture est uniquement rappeler pour information ici:
Function DmGetRenameOptions(RequestDocId As String) As Integer
Dim ret As String, i As Integer, ArgKey As String, ArgVal As String
ret = dmAPIExec("fetch,c," & RequestDocId)
If ret = 0 Then
Call DmPrint("Could not fetch the job request document " & _
RequestDocId & ".", "fatal")
Else
ret = dmAPISet("set,c," & RequestDocId & ",request_completed", "T")
ret = dmAPIExec("save,c," & RequestDocId)
If ret = 0 Then
Call DmPrint("Could not update completion ret of " & _
"job request document " & RequestDocId & ".", "fatal")
End If
End If
For i = 0 to 3
ArgKey = dmAPIGet("get,c," & RequestDocId & _
",arguments_keys[" & i & "]")
ArgVal = dmAPIGet("get,c," & RequestDocId & _
",arguments_values[" & i & "]")
If (ArgKey = "OldUserName") Then
OldUserName = ArgVal
Call DmEscapeSingleQuotes(OldUserName, DqlOldUserName)
Elseif(ArgKey = "NewUserName") Then
NewUserName = ArgVal
Call DmEscapeSingleQuotes(NewUserName, DqlNewUserName)
ElseIf(ArgKey = "report_only") Then
If (ArgVal = "F") Then
ReportOnly = false
Elseif(ArgVal = "T") Then
ReportOnly = true
Else
DmGetRenameOptions = 0
Call DmPrint("Invalid option " & ArgVal & _
" was specified for the execution mode of the rename job.", "error")
exit function
End If
Elseif(ArgKey = "unlock_locked_obj") Then
If (ArgVal = "F") Then
UnlockLckObj = false
Elseif(ArgVal = "T") Then
UnlockLckObj = true
Else
DmGetRenameOptions = 0
Call DmPrint("Invalid option " & ArgVal & _
" was specified for the locked (checked out) object.", "error")
exit function
End If
Else
DmGetRenameOptions = 0
Call DmPrint("Invalid argument key '" & ArgKey & _
"' was specified.", "error")
exit function
End If
Next
DmGetRenameOptions = 1
End Function
Ici, les variables suivantes sont peuplées pour chaque demande de changement de nom:
Variable | Contenu |
---|---|
OldUserName | Le nom à modifier. |
NewUserName | Le nouveau nom. |
ReportOnly | Indique si les modifications sont sauvegardées ou est ce que juste un rapport est réalisé. |
UnlockLckObj | Indique si les objets vérrouillés doivent être dévérouillés ou non. |
Modifications
Jusqu'à présent, seuls des rappels ont été présentés. Le modifications (ou rapport) sont réellement exécutées dans la fonction DmUserRename
:
Sub DmUserRename(MethodTraceLevel As String)
Dim ExecModeStr As String, LockModeStr As String, QueryStr As String
Call DmPrint("==============" & Format$(now) & "===============", _
"information")
If(ReportOnly = true) Then
Call DmPrint("Reporting potential changes in docbase " & _
DocbaseName, "information")
Call DmPrint("when renaming user '" & OldUserName & _
"' to '" & NewUserName & "'.", "information")
ExecModeStr = "Report Only"
Else
Call DmPrint("Renaming User '" & OldUserName & "' to '" & _
NewUserName & "' in docbase " & DocbaseName, "information")
ExecModeStr = "Save Changes"
End If
If(UnlockLckObj = true) Then
LockModeStr = "Unlock"
Else
LockModeStr = "Ignore"
End If
Call DmPrint(" ", "information")
Call DmPrint("The following user rename options were specified:", _
"information")
Call DmPrint("Execution Mode: " & ExecModeStr, "information")
Call DmPrint("Checked out Objects: " & LockModeStr, "information")
If (NewUserName = OldUserName) Then
Call DmPrint("Nothing to do because the new name '" & NewUserName & _
"' is the same as the old one '" & OldUserName & "'", "information")
Exit Sub
End If
If MethodTraceLevel > 0 Then Call DefineNumOfSessions()
' Unlock (or only report) sysobjects which are locked by the Old User.
Call DmPrint(" ", "information")
Call DmPrint("====== Sysobjects that are locked and have references to user '" & OldUserName & _
"' =====", "information")
If(UnlockLckObj = true) then
Call DmPrint("(all the objects in this list will be unlocked)", _
"information")
Else
Call DmPrint("(all the objects in this list will remain locked)", _
"information")
End If
Call DmPrint(" ", "information")
QueryStr$ = "query,c,select r_object_id from " & _
"dm_sysobject (all) where " & _
"(owner_name = '" & DqlOldUserName & "' or " & _
"r_creator_name = '" & DqlOldUserName & "' or " & _
"r_modifier = '" & DqlOldUserName & "' or " & _
"acl_domain = '" & DqlOldUserName & "' or " & _
"r_lock_owner = '" & DqlOldUserName & "') and " & _
"r_lock_owner <> ' '"
Call DmUpdateSysobj("unlock", QueryStr)
Call DmRenameDmUserObj()
' Now that user object is updated we need to write to federation log.
Call DmWriteToFedLog()
' Update Acl Objects.
Call DmPrint(" ", "information")
Call DmPrint("===== ACL Objects referencing user " & OldUserName & _
" ====", "information")
Call DmPrint(" ", "information")
Call DmUpdateACLs()
' Update Alias Set Objects.
Call DmPrint(" ", "information")
Call DmPrint("===== Alias Set Objects referencing user " & OldUserName & _
" ====", "information")
Call DmPrint(" ", "information")
Call DmUpdateAliasSets()
' If user's default acl is still pointing to the old user name, then
' update it.
Call DmUpdateUsrDefACL()
' Update (or only report) sysobjects which are not locked.
Call DmPrint(" ", "information")
Call DmPrint("====== Sysobjects referencing user '" & OldUserName & _
"', which are not locked =====", "information")
Call DmPrint(" ", "information")
QueryStr$ = "query,c,select r_object_id from " & _
"dm_sysobject (all) where " & _
"(owner_name = '" & DqlOldUserName & "' or " & _
"r_creator_name = '" & DqlOldUserName & "' or " & _
"r_modifier = '" & DqlOldUserName & "' or " & _
"acl_domain = '" & DqlOldUserName & "' or " & _
"r_lock_owner = '" & DqlOldUserName & "') and " & _
"r_lock_owner = ' '"
Call DmUpdateSysobj("", QueryStr)
' Update (or only report) sysobjects which are locked.
Call DmPrint(" ", "information")
Call DmPrint("====== Sysobject referencing user '" & OldUserName & _
"', which are locked =====", "information")
If(UnlockLckObj = true) then
Call DmPrint("(all the objects in this list will be " & _
"unlocked and modified)", "information")
Else
Call DmPrint("(all the objects in this list will remain locked " & _
" and will not be modified)", "information")
End If
Call DmPrint(" ", "information")
QueryStr$ = "query,c,select r_object_id from " & _
"dm_sysobject (all) where " & _
"(owner_name = '" & DqlOldUserName & "' or " & _
"r_creator_name = '" & DqlOldUserName & "' or " & _
"r_modifier = '" & DqlOldUserName & "' or " & _
"acl_domain = '" & DqlOldUserName & "' or " & _
"r_lock_owner = '" & DqlOldUserName & "') and " & _
"r_lock_owner <> ' '"
Call DmUpdateSysobj("", QueryStr)
' Update Workflow and related objects.
Call DmPrint(" ", "information")
Call DmPrint("====== Workflow and related objects referencing user " & OldUserName & _
". ======", "information")
Call DmPrint(" ", "information")
Call DmUpdateWorkflow()
' Update groups referencing the Old User.
Call DmPrint(" ", "information")
Call DmPrint("====== Groups referencing user " & OldUserName & _
". ======", "information")
Call DmPrint(" ", "information")
Call DmUpdateGroups()
' Delete the old user object after the references in group objects are
' updated. Otherwise, the old user entries will be removed when the
' user object is destroyed.
If(DeleteOldUser = true) Then
Call DmDeleteOldUserObj()
End If
' Update dmi_registry objects (reregister)
Call DmPrint(" ", "information")
Call DmPrint("====== dmi_registry objects referencing user " & _
OldUserName & ". ======", "information")
Call DmPrint(" ", "information")
Call DmUpdateDmiRegistry()
' List all the dm_registered, dm_type and dmi_type_info objects
' referencing the old user. The script does not modify objects,
' administrators have to do it manually.
Call DmPrint("====== The following dm_registered objects have " & _
"table_owner attribute", "information")
Call DmPrint(" referencing user " & OldUserName & _
". The script will not update", "information")
Call DmPrint(" the objects. You have to modify them manually.", _
"information")
Call DmListDm_registeredObj()
Call DmPrint(" ", "information")
' Update category_owner attribute in dm_category objects referencing the Old User.
Call DmPrint("====== dm_category objects referencing user " & OldUserName & _
". ======", "information")
Call DmPrint(" ", "information")
call DmUpdate_Dm_Category()
Call DmPrint(" ", "information")
Call DmPrint("====== The following dm_type objects have " & _
"owner_name attribute", "information")
Call DmPrint(" referencing user " & OldUserName & _
". The script will not update", "information")
Call DmPrint(" the objects. You have to modify them manually.", _
"information")
Call DmListDm_typeObj()
Call DmPrint("====== The following dmi_type_info objects have " & _
"acl_domain attribute", "information")
Call DmPrint(" referencing user " & OldUserName & _
". The script will not update", "information")
Call DmPrint(" the objects. You have to modify them manually.", _
"information")
Call DmListDmi_type_infoObj()
Call DmPrint("--------" & Format$(now) & "--------", "information")
End Sub
Le principe est d'exécuter une recherche, en fonction du type, pour identifier toutes les instances d'objets à modifier, puis d'effectuer le changement de valeur sur les attributs concernés. Pour certains types d'objet, la modification est réalisée directement en SQL car des objets ne sont théoriquement pas modifiables.
Les modifications apportées concernent:
Type d'objet | Mode recherche | Mode modification | Attributs modifiés |
---|---|---|---|
dm_sysobject | Requête DQL sur les objets vérouillés. | API unlock. | Enlève le verrou sur les objets vérrouillés qui doivent être modifiés. |
dm_user | API retrieve. | API set puis save. | user_name. |
dm_federation_log | DQL. | Injection d'une information de rename pour la fédération. | |
dm_acl | SQL. | owner_name, r_accessor_name. | |
dm_alias_set | Requête DQL. | API set puis save. | owner_name et alias_value. |
dm_alias_set | Requête DQL. | API set puis save. | owner_name et alias_value. |
dm_user | API retrieve. | API set puis save. | acl_domain. |
dm_sysobject | Requête DQL sur les objets non vérouillés. | API set puis save, ou SQL. | owner_name, r_creator_name, r_modifier, acl_domain, r_lock_owner en API.
r_modifier en SQL. En effet, la modification de r_modifier étant gérer par le serveur, il est impossible de mettre à jour la valeur en API. |
dm_sysobject | Requête DQL sur les objets vérouillés. | API set puis save, ou SQL. | owner_name, r_creator_name, r_modifier, acl_domain, r_lock_owner en API.
r_modifier en SQL. En effet, la modification de r_modifier étant gérer par le serveur, il est impossible de mettre à jour la valeur en API. |
Informations sur les workflows. | SQL. | La liste est trop importante pour être décrite dans le cadre de cet article. Et il n'y a aucune optimisation à apporter. | |
dm_group | SQL. | users_names, owner_name et group_admin. | |
dmi_registry | Requête DQL. | API register. | |
dm_registered | Requête DQL. | Aucune modification n'est apportée. Seule un warning est affichée dans la log. | |
dm_category | SQL. | category_owner. | |
dm_type | Requête DQL. | Aucune modification n'est apportée. Seule un warning est affichée dans la log. | |
dmi_type_info | Requête DQL. | Aucune modification n'est apportée. Seule un warning est affichée dans la log. |
Optimisations
Pour plusieurs modifications, la récupération des objets à modifier est effectuée à l'aide d'une requête DQL avec plusieurs critères de filtre séparés par l'opérateur OR
. Et c'est cette organisation des filtres qui est le source des potentielles lenteurs d'exécution. De manière générale, il faut éviter cet opérateur quand cela est possible, ce qui est largement le cas dans cette méthode.
Pour ce faire, il suffit de modifier les requêtes en préférant l'utilisation de sous requête imbriquées avec l'opérateur UNION
.
Unlock dm_sysobject
La actions sur les instances de dm_sysobject
utilise la requête suivante:
QueryStr$ = "query,c,select r_object_id from " & _
"dm_sysobject (all) where " & _
"(owner_name = '" & DqlOldUserName & "' or " & _
"r_creator_name = '" & DqlOldUserName & "' or " & _
"r_modifier = '" & DqlOldUserName & "' or " & _
"acl_domain = '" & DqlOldUserName & "' or " & _
"r_lock_owner = '" & DqlOldUserName & "') and " & _
"r_lock_owner <> ' '"
Elle est transformée ainsi:
QueryStr$ = "query,c,select r_object_id from dm_sysobject (all) where owner_name = '" & DqlOldUserName & "' and r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_creator_name = '" & DqlOldUserName & "' and r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_modifier = '" & DqlOldUserName & "' and r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where acl_domain = '" & DqlOldUserName & "' and r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_lock_owner = '" & DqlOldUserName & "'"
Il est évité de chercher les objets donc la valeur de r_lock_owner
est l'ancien nom et est différent de chaîne vide, le second étant forcément vrai.
Modification dm_alias_set
La requête à modifier se trouve dans la fonction DmUpdateAliasSets
:
DmQuery = dmAPIGet("query,c,select r_object_id from dm_alias_set where " & _
"owner_name = '" & DqlOldUserName & "' or " & _
"any alias_value = '" & DqlOldUserName & "'")
Elle est transformée ainsi:
DmQuery = dmAPIGet("query,c,select r_object_id from dm_alias_set where owner_name = '" & DqlOldUserName & "' " & _
"union select r_object_id from dm_alias_set where any alias_value = '" & DqlOldUserName & "'")
Modification dm_sysobject non vérrouillé
Les instances de dm_sysobject
non vérouillées sont cherchées à partir de la requête suivante:
QueryStr$ = "query,c,select r_object_id from " & _
"dm_sysobject (all) where " & _
"(owner_name = '" & DqlOldUserName & "' or " & _
"r_creator_name = '" & DqlOldUserName & "' or " & _
"r_modifier = '" & DqlOldUserName & "' or " & _
"acl_domain = '" & DqlOldUserName & "' or " & _
"r_lock_owner = '" & DqlOldUserName & "') and " & _
"r_lock_owner = ' '"
Il est assez drôle de voir qu'un des filtres porte sur le nom à modifier dans l'attribut r_lock_owner
, alors qu'il y a un filtre global indiquant que r_lock_owner
doit être une chaîne vide. Bien entendu, cette erreur, sans grand impact, ne sera pas reproduite dans le cadre de cette optimisation.
La requête est transformée ainsi:
QueryStr$ = "query,c,select r_object_id from dm_sysobject (all) where owner_name = '" & DqlOldUserName & "' and r_lock_owner = ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_creator_name = '" & DqlOldUserName & "' and r_lock_owner = ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_modifier = '" & DqlOldUserName & "' and r_lock_owner = ' ' " & _
"union select r_object_id from dm_sysobject (all) where acl_domain = '" & DqlOldUserName & "' and r_lock_owner = ' '"
Modification dm_sysobject vérrouillé
Les instances de dm_sysobject
vérouillées sont cherchées à partir de la requête suivante:
QueryStr$ = "query,c,select r_object_id from " & _
"dm_sysobject (all) where " & _
"(owner_name = '" & DqlOldUserName & "' or " & _
"r_creator_name = '" & DqlOldUserName & "' or " & _
"r_modifier = '" & DqlOldUserName & "' or " & _
"acl_domain = '" & DqlOldUserName & "' or " & _
"r_lock_owner = '" & DqlOldUserName & "') and " & _
"r_lock_owner <> ' '"
Cette requête est similaire à celle pour les instances non vérouillées. De plus, comme pour la suppression du verrou, il sera évité de chercher les objets donc la valeur de r_lock_owner
est l'ancien nom et est différente de chaîne vide, le second étant forcément vrai.
La requête est transformée ainsi:
QueryStr$ = "query,c,select r_object_id from dm_sysobject (all) where owner_name = '" & DqlOldUserName & "' r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_creator_name = '" & DqlOldUserName & "' r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_modifier = '" & DqlOldUserName & "' r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where acl_domain = '" & DqlOldUserName & "' r_lock_owner <> ' ' " & _
"union select r_object_id from dm_sysobject (all) where r_lock_owner = '" & DqlOldUserName & "'"
Modification dm_router
Les instances de dm_router
sont identifiées dans la méthode DmUpdateRouters
:
DmQuery = dmAPIGet("query,c,select r_object_id from dm_router (all) " & _
"where supervisor_name = '" & DqlOldUserName & "' or" & _
" any task_owner = '" & DqlOldUserName & "' or" & _
" any r_task_user = '" & DqlOldUserName & "'")
La requête est transformée ainsi:
DmQuery = dmAPIGet("query,c,select r_object_id from dm_router (all) where supervisor_name = '" & DqlOldUserName & "' " & _
"union select r_object_id from dm_router (all) where any task_owner = '" & DqlOldUserName & "' " & _
"union select r_object_id from dm_router (all) where any r_task_user = '" & DqlOldUserName & "'"
Recherche dm_workflow
Les instances de dm_workflow
sont identifiées dans la méthode DmUpdateDm_Wrkflws
:
DmQuery = dmAPIGet("query,c,select r_object_id " & _
"from dm_workflow where " & _
"r_creator_name = '" & DqlOldUserName & "' or " & _
"supervisor_name = '" & DqlOldUserName & "' or " & _
"any r_performers = '" & DqlOldUserName & "' or " & _
"any r_last_performer = '" & DqlOldUserName & "'")
La requête est transformée ainsi:
DmQuery = dmAPIGet("query,c,select r_object_id from dm_workflow where r_creator_name = '" & DqlOldUserName & "' " & _
"union select r_object_id from dm_workflow where supervisor_name = '" & DqlOldUserName & "' " & _
"union select r_object_id from dm_workflow where any r_performers = '" & DqlOldUserName & "' " & _
"union select r_object_id from dm_workflow where any r_last_performer = '" & DqlOldUserName & "'")
Recherche dmi_workitem
Les instances de dmi_workitem
sont identifiées dans la méthode DmUpdateDm_Wrkitm
:
DmQuery = dmAPIGet("query,c,select r_object_id " & _
"from dmi_workitem where " & _
"r_performer_name = '" & DqlOldUserName & "' or " & _
"any r_ext_performer = '" & DqlOldUserName & "'")
La requête est transformée ainsi:
DmQuery = dmAPIGet("query,c,select r_object_id from dmi_workitem where r_performer_name = '" & DqlOldUserName & "' " & _
"union select r_object_id from dmi_workitem where any r_ext_performer = '" & DqlOldUserName & "'")
Recherche dmi_queue_item
Les instances de dmi_queue_item
sont identifiées dans la méthode DmUpdateDmiQueue
:
DmQuery = dmAPIGet("query,c,select r_object_id from dmi_queue_item " & _
"where " & _
"name = '" & DqlOldUserName & "' or " & _
"sent_by = '" & DqlOldUserName & "' or " & _
"supervisor_name = '" & DqlOldUserName & "' or " & _
"dequeued_by = '" & DqlOldUserName & "' or " & _
"sign_off_user = '" & DqlOldUserName & "'")
A noter, il est amusant de constater le formattage de la requête juste dans cette méthode, afin d'avoir le signe =
sur la même colonne. Ce principe n'est quasiment repris nulle part, à croire qu'un développeur s'est amusé un jour... Mais bon ceci n'est pas très important.
La requête est transformée ainsi:
DmQuery = dmAPIGet("query,c,select r_object_id from dmi_queue_item where name = '" & DqlOldUserName & "' " & _
"union select r_object_id from dmi_queue_item where sent_by = '" & DqlOldUserName & "' " & _
"union select r_object_id from dmi_queue_item where supervisor_name = '" & DqlOldUserName & "' " & _
"union select r_object_id from dmi_queue_item where dequeued_by = '" & DqlOldUserName & "' " & _
"union select r_object_id from dmi_queue_item where sign_off_user = '" & DqlOldUserName & "'")
Optimisation annexe
A la lecture du code, une modification est possible mais ne concernant pas les requêtes. Dans ce cas, c'est unique un principe de bonne pratique dans le language de programmation. Le code de la fonction DmUpdateDmiRegistry
est le suivant:
Sub DmUpdateDmiRegistry()
Dim ret As Integer
Dim NumOfObj As String
NumOfObj = countUsrRegistryObjs(DqlOldUserName)
Call DmPrint("dmi_registry objects " & _
"referencing user " & DqlOldUserName & " are " & countUsrRegistryObjs(DqlOldUserName) , "information")
If NumOfObj <> "0" Or NumOfObj <> "" Then
Call DmRegisterForNewUser()
Call DmPrint("dmi_registry objects " & _
"referencing user " & DqlNewUserName & " are " & countUsrRegistryObjs(DqlNewUserName) , "information")
End If
End Sub
Il paraît évident que le deuxième appel à countUsrRegistryObjs(DqlOldUserName)
est inutile puisque son résultat a déjà été stocké dans la variable NumOfObj
. La fonction est transformée ainsi:
Sub DmUpdateDmiRegistry()
Dim ret As Integer
Dim NumOfObj As String
NumOfObj = countUsrRegistryObjs(DqlOldUserName)
' Call DmPrint("dmi_registry objects " & _
' "referencing user " & DqlOldUserName & " are " & countUsrRegistryObjs(DqlOldUserName) , "information")
Call DmPrint("dmi_registry objects " & _
"referencing user " & DqlOldUserName & " are " & NumOfObj , "information")
If NumOfObj <> "0" Or NumOfObj <> "" Then
Call DmRegisterForNewUser()
Call DmPrint("dmi_registry objects " & _
"referencing user " & DqlNewUserName & " are " & countUsrRegistryObjs(DqlNewUserName) , "information")
End If
End Sub
Installation optimisation
Le fichier modifié est disponible, pour la version 6.7 SP1, ici userrename optimisé.ebs.gz. Attention, ce fichier n'est pas officiel et je ne pourrai être tenu responsable en cas de corruption des données, même si je ne vois pas pourquoi cela se produirait.
Il y a deux possibilités pour l'installer:
- Soit le fichier vient remplacer celui installé en standard, en ayant fait une sauvegarde au préalable.
- Soit, afin de conserver le support Editeur, il faut faire des copies du job
dm_UserRename
et de la méthodedm_UserRename
.
La deuxième solution est conseillée et détaillée, ainsi il est possible de conserver le fonctionnement standard.
Copie du fichier
Après téléchargement du fichier userrename optimisé.ebs.gz
, il faut en extratire le fichier userrename.ebs
et le déposer sous le nom userrename_optimized.ebs
dans le répertoire <DCTM INSTALL DIR>\install\admin\
, dans le même emplacement que le fichier original.
Copie de la méthode
Il faut ensuite créer une nouvelle méthode serveur qui va utiliser ce nouveau fichier. Ceci s'effectue simplement en API:
API> set,c,l,object_name SET> dm_UserRename_Optimized ... OK API> set,c,l,method_verb SET> ..\install\admin\userrenam_optimized.ebd -eUserRename ... OK API> saveasnew,c,l ... 1000000180021121
Copie du job
Il faut ensuite créer un nouveau job lié avec cette nouvelle méthode serveur. Ceci s'effectue simplement en API:
API> retrieve,c,dm_job where object_name='dm_UserRename' ... 0800000180000373 API> get,c,l,method_name ... dm_UserRename API> set,c,l,object_name SET> dm_UserRename_Optimized ... OK API> set,c,l,method_name SET> dm_UserRename_Optimized ... OK API> saveasnew,c,l ... 080000018002112a
Par contre, il ne sera pas pris en compte lors de la demande de renommage sous DA. En effet, lorsqu'il est demandé d'effectuer le renommage tout de suite après la création de la demande, le job est recherché avec le nom dm_UserRename
.
Enfin, il suffit de désactiver le job standard:
API> retrieve,c,dm_job where object_name='dm_UserRename' ... 0800000180000373 API> set,c,l,is_inactive SET> T ... OK API> save,c,l ... 080000018002112a