Friday, April 27, 2012

How to set the same content on multiple objects

There are situations when you want to set the same content on more objects. If you use the standard approach of setting content on each object, because a content object (dmr_content) will be created per each document object. On one hand it's a bit of redundancy, isn't it? On the other - if you change one content, the other (related) contents won't be updated.
That's why it's more convenient to set (link) one content object to multiple document objects, action known as binding.
You can bind an existing content of an object to another object via DFC code or an API call.

API> bindfile,c,[TARGET_ID],0,[SRC_ID],0

where:
TARGET_ID - the id of the sysobject you are binding to
0 - the position of the content in the object (0 is the first/primary content)
SRC_ID - the id of the source object that the content is assigned (linked) to
DFC code:
IDfId childId = new DfId("[target id]");
IDfId parentId = new DfId("[source id]");
IDfSysObject sysobject = session.getObject(childId);
sysobject.bindFile(0, parentId, 0);
sysobject.save();

Wednesday, April 25, 2012

How to unlock a job in running state

There are situations when a running job fails and remains locked in running state. It usually happens when the JMS is stopped or other fatal errors occur.
To unlock such a job, the following steps should be performed (in this order until it's unlocked).

1) Check if the job is locked, using the following DQL:
select r_lock_date from dm_job where job_name='[JOB_NAME]'

if the returned value is not nulldate, the job is locked. Unlock it by executing the API command:
unlock,c,[r_object_id]

2) If the job is still in running state, perhaps the job's process is still active (hung) and must be killed.
a. Get the process ID, using the DQL:
select a_last_process_id from dm_job where object_name='[JOB_NAME]'
b. Using Process Explorer (or similar) locate the process by id and kill it
c. Check the job state (in DA)
3) Checked the job and it's still running? Don't give up, we're almost done!
Check the a_current_status attribute value (DQL: select a_current_status from dm_job where object_name='[JOB_NAME]').
If it's 'STARTED', we should change it to 'FAILED'. Use the following DQL:
update dm_job object set a_current_status='FAILED' where object_name='[JOB_NAME]'

4) If your job still didn't get rid of the running status, perhaps it has the reference to the application that locked it.
Execute the DQL query:
select r_object_id, a_last_invocation, a_last_completion, a_special_app from dm_job where (((a_last_invocation IS NOT NULLDATE)
 and (a_last_completion IS NULLDATE)) or (a_special_app = 'agentexec')) and (i_is_reference = 0 OR i_is_reference is NULL)
 and (i_is_replica = 0 OR i_is_replica is NULL)

If the query returns your job, execute the following DQL:
update dm_job objects set a_special_app='' where object_name='[JOB_NAME]'

That's it, your job is unlocked now and ready to be run again.

Monday, April 23, 2012

How to change a job's scheduled run time

Even if you have changed the scheduled time for a job to run (using DA, on the job properties, schedule tab), you will notice the the job continues to run at the old time.
What's wrong? Let's have a look behind the curtains!
The agent_exec pols the a_next_invocation attribute of the dm_job object to determine when the job should run next.
In fact, when you update the job schedule, this attribute is not updated (it is when the job runs). So, you have to update it manually and the 2 options are:

1. API (using DA or other client):
retrieve,c,dm_job where object_name='[JOB_NAME]'
set,c,l,a_next_invocation
04/09/2012 19:00:00
save,c,l
2. DQL:
update dm_job object set a_next_invocation=DATE('04/09/2012 19:00:00','mm/dd/yyyy hh:mi:ss') where object_name='[JOB_NAME]'

If your changes had no effect, perhaps you have to reinitialize the Content Server process (thread). Use the following API command for that:
reinit,c

LDAP Sync - Solve user name conflicts

When an AD (Active Directory) user object name is changed (userPrincipalName,sAMAccountName, or other attributes) and later another AD object is created with the original name of the first user object, a conflict in the LDAPSync'ed repository occurs.
This is caused by the fact that user_name attribute of the dm_user objects is not changed during LDAP Synchronization (by default user rename option is disabled in LDAP config object) - thus another object with same value can't be created (as this field is unique).
Another conflict situation could be when 1 repository is sync'ed against several AD domains and some user name values might be equal across domains.

The steps to solve this conflict are:
1. Rename the old user object in the repository
(user_login_name has changed while user_name still holds the old value).
For this: open DA, Users section, search for the user, right-click on it and choose Reassign User option.
In the Reassign field enter the new user name (should be current user_login_name value).
Select the option 'Run the Reassign job Now'.
If the user has locked objects, perhaps it's better to select Checked Out Objects Leave all locked (though if the user is inactive, perhaps it's better to unlock).
Press Ok to perform the changes, which will start the dm_UserRename job shortly.
2. Check the dm_UserRename job report
Search for the dm_UserRename job and check if it is running or already completed (after your change at step 1), or if it didn’t start yet (CS can be loaded with other jobs) wait until it runs. Notice that usually the job is in inactive state, but this is normal.
After the run has completed (see Last Run column value), view the job report (from context menu) and check that the user has been renamed, if there were some issues or if some repository objects still have references to the old value.

3. Run immediately the dm_LDAPSynchronization job (optional)
Running this job manually is not mandatory as it usually runs by schedule. However, if the user updates are urgent, the job can be run manually, but an additional trick must be performed in order to not disturb the time intervals of the synchronizations. Perform the following steps:

a) Retrieve the a_last_run and a_last_no from the ldap config object and store them:
DQL> select a_last_run,a_last_no from dm_ldap_config
a_last_run                            a_last_no        
================ ============
20091105210022.0Z         195290415        

b) Store the current value of dm_ldap_config.per_search_filter, then change it (to update only the 1 required user) to:
DQL> update dm_ldap_config object set per_search_filter='(&(userPrincipalName=MY_USER*)(mail=*))'
(assuming 'MY_USER' is the new user to be created, which failed due to the conflict. You can leave the old filter and just add an additional contidion: (userPrincipalName=MY_USER*) )

c) Run the dm_LDAPSynchronization job. Check the report and see if the user has been created properly. Also check the user is indeed created (using DA/samson/other client)

d) Restore previous ldap config object settings:
update dm_ldap_config object set a_last_run='20091105210022.0Z',set a_last_no='195290415', set per_search_filter='[ORIGINAL_VALUE]'