aspects or not aspects…

Some time ago I wrote a post about no progress in Documentum platform, and the opinion about aspects feature was, I would say, neutral rather than negative, now, after two years of using aspects I can say without doubts: never ever use Documentum aspects, avoid repeating my mistake – EMC’s implementations is completely unreliable and slow. Let’s explain…

At first, I do not want to discuss DFC Aspect Model:

because it hard to imagine situation when you really need to build TBO classes in runtime – EMC tried use this feature in XCP2 and had failed. So, this feature is defective by design, and I would like to talk about additional attributes which we can introduce using aspects.

Well, how does Content Server behave when it fetches aspect-enabled objects? Let’s discover it’s behaviour using previously demonstrated technique (I specially issue two fetches because the first one performs a lot of irrelevant caching queries related to information about types and TBOs):

Connected to Documentum Server running Release 7.2.0030.0195  Linux64.Oracle
Session id is s0
API> apply,c,,SQL_TRACE,SESSION_ID,S,01024be980005db7,LEVEL,I,10
...
q0
API> ?,c,q0
result      
------------
T           
(1 row affected)

API> fetch,c,09024be98001f94e
...
OK
API> fetch,c,09024be98001f94f
...
OK
API> Bye

and the result is:

-- determine object type by r_object_id
SELECT dm_dbalias_B.I_TYPE
  FROM DMI_OBJECT_TYPE dm_dbalias_B
 WHERE dm_dbalias_B.R_OBJECT_ID = :dmb_handle;

-- retrieve object's data from database
  SELECT *
    FROM CUSTOM_TYPE_RV dm_dbalias_B, CUSTOM_TYPE_SV dm_dbalias_C
   WHERE (    dm_dbalias_C.R_OBJECT_ID = :dmb_handle
          AND dm_dbalias_C.R_OBJECT_ID = dm_dbalias_B.R_OBJECT_ID)
ORDER BY dm_dbalias_B.R_OBJECT_ID, dm_dbalias_B.I_POSITION;

-- retrieve aspect's data from database
  SELECT *
    FROM DMI_03024BE98000025B_RV dm_dbalias_B,
         DMI_03024BE98000025B_SV dm_dbalias_C
   WHERE (    dm_dbalias_C.R_OBJECT_ID = :dmb_handle
          AND dm_dbalias_C.R_OBJECT_ID = dm_dbalias_B.R_OBJECT_ID)
ORDER BY dm_dbalias_B.R_OBJECT_ID, dm_dbalias_B.I_POSITION;

-- check whether object is actual or not
SELECT dm_dbalias_B.R_OBJECT_ID
  FROM DM_SYSOBJECT_S dm_dbalias_B
 WHERE (    dm_dbalias_B.R_OBJECT_ID = :dmb_objectp
        AND dm_dbalias_B.I_VSTAMP = :dmb_versionp);

If you compare these queries with queries described in What happens when smart guy does not sit back blogpost you will find that the existence of aspect introduces two new queries, i.e.:

-- retrieve aspect's data from database
  SELECT *
    FROM DMI_03024BE98000025B_RV dm_dbalias_B,
         DMI_03024BE98000025B_SV dm_dbalias_C
   WHERE (    dm_dbalias_C.R_OBJECT_ID = :dmb_handle
          AND dm_dbalias_C.R_OBJECT_ID = dm_dbalias_B.R_OBJECT_ID)
ORDER BY dm_dbalias_B.R_OBJECT_ID, dm_dbalias_B.I_POSITION;

-- check whether object is actual or not
SELECT dm_dbalias_B.R_OBJECT_ID
  FROM DM_SYSOBJECT_S dm_dbalias_B
 WHERE (    dm_dbalias_B.R_OBJECT_ID = :dmb_objectp
        AND dm_dbalias_B.I_VSTAMP = :dmb_versionp);

So, it is obvious that aspects have negative performance impact, what about reliability? Try to guess what is the purpose of the last select statement:

-- check whether object is actual or not
SELECT dm_dbalias_B.R_OBJECT_ID
  FROM DM_SYSOBJECT_S dm_dbalias_B
 WHERE (    dm_dbalias_B.R_OBJECT_ID = :dmb_objectp
        AND dm_dbalias_B.I_VSTAMP = :dmb_versionp);

Though, there is much simpler question – why, when fetching object’s data from database, Content Server issues following statement:

  SELECT *
    FROM CUSTOM_TYPE_RV dm_dbalias_B, CUSTOM_TYPE_SV dm_dbalias_C
   WHERE (    dm_dbalias_C.R_OBJECT_ID = :dmb_handle
          AND dm_dbalias_C.R_OBJECT_ID = dm_dbalias_B.R_OBJECT_ID)
ORDER BY dm_dbalias_B.R_OBJECT_ID, dm_dbalias_B.I_POSITION;

but not two much more simple statements:

  SELECT *
    FROM CUSTOM_TYPE_SV dm_dbalias_C
   WHERE (    dm_dbalias_C.R_OBJECT_ID = :dmb_handle);

  SELECT *
    FROM CUSTOM_TYPE_RV dm_dbalias_B
   WHERE (    dm_dbalias_B.R_OBJECT_ID = :dmb_handle)
ORDER BY dm_dbalias_B.R_OBJECT_ID, dm_dbalias_B.I_POSITION;

?

The clue for the last question is a statement-level read consistency, i.e. in case of single query the result is always consistent, in case of two queries – doesn’t. Now the purpose of the last select statement in aspect example is clear: Content Server successively retrieves object’s data, aspect’s data, and after that Content Server checks whether the object have been changed since the first query or not. And now the most interesting thing: what happens if last select statement returns nothing? Nothing good. It is really hard to reproduce the situation but I have succeeded and wrote following test case:

/**
 * @author Andrey B. Panfilov <andrey@panfilov.tel>
 */
public class DfExceptionsTest extends DfcTestSupport {

    @Test
    @Ignore
    public void testSoftFetch() throws Exception {
        final IDfSession s1 = Sessions.brandNew(getSession()
                .getSessionManager(), getSession().getDocbaseName());
        final IDfSession s2 = Sessions.brandNew(getSession()
                .getSessionManager(), getSession().getDocbaseName());

        TestFetch testFetch = new TestFetch(s2, "09024be98001f94e");
        Thread t = new Thread(testFetch);
        t.start();

        ApplyExecSQL cmd = (ApplyExecSQL) DfAdminCommand
                .getCommand(IDfAdminCommand.APPLY_EXEC_SQL);
        cmd.setQuery("update dm_sysobject_s set i_vstamp=i_vstamp+1 "
                + "where r_object_id='09024be98001f94e'");

        for (int i = 0; i < 10000; i++) {
            cmd.execute(s1);
        }

        t.interrupt();
        assertFalse(testFetch._failed);
    }

    class TestFetch implements Runnable {

        private final IDfSession _session;

        private final String _objectId;

        private boolean _failed;

        public TestFetch(IDfSession session, String objectId) {
            _session = session;
            _objectId = objectId;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 100000; i++) {
                    _session.getObject(DfIdUtil.getId(_objectId));
                    _session.flushObject(DfIdUtil.getId(_objectId));
                }
            } catch (DfException ex) {
                ex.printStackTrace();
                _failed = true;
            }
        }
    }

}

which reproduces two different exceptions:

DfException:: THREAD: Thread-9; MSG: [DM_OBJ_MGR_E_UNABLE_TO_FETCH_CONSISTENT_OBJECT_SNAPSHOT]
   error:  "Unable to fetch object 09024be98001f94e alongwith its aspect attributes with consistency"; ERRORCODE: 100; 
NEXT: null
	at com.documentum.fc.client.impl.docbase.DocbaseExceptionMapper.newException(DocbaseExceptionMapper.java:57)
	at com.documentum.fc.client.impl.connection.docbase.MessageEntry.getException(MessageEntry.java:39)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseMessageManager.getException(DocbaseMessageManager.java:137)
	at com.documentum.fc.client.impl.connection.docbase.netwise.NetwiseDocbaseRpcClient.checkForMessages(NetwiseDocbaseRpcClient.java:310)
	at com.documentum.fc.client.impl.connection.docbase.netwise.NetwiseDocbaseRpcClient.applyForObject(NetwiseDocbaseRpcClient.java:653)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection$8.evaluate(DocbaseConnection.java:1380)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection.evaluateRpc(DocbaseConnection.java:1139)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection.applyForObject(DocbaseConnection.java:1372)
	at com.documentum.fc.client.impl.docbase.DocbaseApi.parameterizedFetch(DocbaseApi.java:107)
	at com.documentum.fc.client.impl.objectmanager.PersistentDataManager.fetchFromServer(PersistentDataManager.java:191)
	at com.documentum.fc.client.impl.objectmanager.PersistentDataManager.getData(PersistentDataManager.java:82)
	at com.documentum.fc.client.impl.objectmanager.PersistentObjectManager.getObjectFromServer(PersistentObjectManager.java:355)
	at com.documentum.fc.client.impl.objectmanager.PersistentObjectManager.getObject(PersistentObjectManager.java:311)
	at com.documentum.fc.client.impl.session.Session.getObject(Session.java:963)
	at com.documentum.fc.client.impl.session.SessionHandle.getObject(SessionHandle.java:653)

and

DfIdNotFoundException:: THREAD: Thread-9; MSG: [DM_API_E_EXIST]
  error:  "Document/object specified by 09024be98001f94e does not exist."; ERRORCODE: 100; 
NEXT: DfException:: THREAD: Thread-9; MSG: [DM_OBJ_MGR_E_UNABLE_TO_FETCH_CONSISTENT_OBJECT_SNAPSHOT]
  error:  "Unable to fetch object 09024be98001f94e alongwith its aspect attributes with consistency"; ERRORCODE: 100; 
NEXT: null
	at com.documentum.fc.client.impl.docbase.DocbaseExceptionMapper.newException(DocbaseExceptionMapper.java:49)
	at com.documentum.fc.client.impl.connection.docbase.MessageEntry.getException(MessageEntry.java:39)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseMessageManager.getException(DocbaseMessageManager.java:137)
	at com.documentum.fc.client.impl.connection.docbase.netwise.NetwiseDocbaseRpcClient.checkForMessages(NetwiseDocbaseRpcClient.java:310)
	at com.documentum.fc.client.impl.connection.docbase.netwise.NetwiseDocbaseRpcClient.applyForObject(NetwiseDocbaseRpcClient.java:653)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection$8.evaluate(DocbaseConnection.java:1380)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection.evaluateRpc(DocbaseConnection.java:1139)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection.applyForObject(DocbaseConnection.java:1372)
	at com.documentum.fc.client.impl.docbase.DocbaseApi.parameterizedFetch(DocbaseApi.java:107)
	at com.documentum.fc.client.impl.objectmanager.PersistentDataManager.fetchFromServer(PersistentDataManager.java:191)
	at com.documentum.fc.client.impl.objectmanager.PersistentDataManager.getData(PersistentDataManager.java:82)
	at com.documentum.fc.client.impl.objectmanager.PersistentObjectManager.getObjectFromServer(PersistentObjectManager.java:355)
	at com.documentum.fc.client.impl.objectmanager.PersistentObjectManager.getObject(PersistentObjectManager.java:311)
	at com.documentum.fc.client.impl.session.Session.getObject(Session.java:963)
	at com.documentum.fc.client.impl.session.SessionHandle.getObject(SessionHandle.java:653)
Caused by: DfException:: THREAD: Thread-9; MSG: [DM_SYSOBJECT_E_CANT_FETCH_INVALID_ID]
  error:  "Cannot fetch a sysobject - Invalid object ID : 09024be98001f94e"; ERRORCODE: 100; 
NEXT: null
	... 19 more
Followed by: DfException:: THREAD: Thread-9; MSG: [DM_OBJ_MGR_E_UNABLE_TO_FETCH_CONSISTENT_OBJECT_SNAPSHOT]
  error:  "Unable to fetch object 09024be98001f94e alongwith its aspect attributes with consistency"; ERRORCODE: 100; 
NEXT: null
	at com.documentum.fc.client.impl.docbase.DocbaseExceptionMapper.newException(DocbaseExceptionMapper.java:57)
	at com.documentum.fc.client.impl.connection.docbase.MessageEntry.getException(MessageEntry.java:39)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseMessageManager.getException(DocbaseMessageManager.java:137)
	at com.documentum.fc.client.impl.connection.docbase.netwise.NetwiseDocbaseRpcClient.checkForMessages(NetwiseDocbaseRpcClient.java:310)
	at com.documentum.fc.client.impl.connection.docbase.netwise.NetwiseDocbaseRpcClient.applyForObject(NetwiseDocbaseRpcClient.java:653)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection$8.evaluate(DocbaseConnection.java:1380)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection.evaluateRpc(DocbaseConnection.java:1139)
	at com.documentum.fc.client.impl.connection.docbase.DocbaseConnection.applyForObject(DocbaseConnection.java:1372)
	at com.documentum.fc.client.impl.docbase.DocbaseApi.parameterizedFetch(DocbaseApi.java:107)
	at com.documentum.fc.client.impl.objectmanager.PersistentDataManager.fetchFromServer(PersistentDataManager.java:191)
	at com.documentum.fc.client.impl.objectmanager.PersistentDataManager.getData(PersistentDataManager.java:82)
	at com.documentum.fc.client.impl.objectmanager.PersistentObjectManager.getObjectFromServer(PersistentObjectManager.java:355)
	at com.documentum.fc.client.impl.objectmanager.PersistentObjectManager.getObject(PersistentObjectManager.java:311)
	at com.documentum.fc.client.impl.session.Session.getObject(Session.java:963)
	at com.documentum.fc.client.impl.session.SessionHandle.getObject(SessionHandle.java:653)

The last one is extremely weird because DFC hides the real error under DfIdNotFoundException. Now let’s check what Content Server thinks about DM_OBJ_MGR_E_UNABLE_TO_FETCH_CONSISTENT_OBJECT_SNAPSHOT error:

SEVERITY: ERROR
DESCRIPTION: D Unable to fetch object %s alongwith its aspect attributes with consistency
CAUSE: This error occurs when a client fetches an object that has aspect attributes, and that either the normal or aspect attributes have changed perhaps by a different session while Content Server was fetching the aspect attributes after fetching the normal attributes from the database.
ACTION: Application should refetch the object.
PARAMS:

Why does the fucking DFC do not reiterate fetch after DM_OBJ_MGR_E_UNABLE_TO_FETCH_CONSISTENT_OBJECT_SNAPSHOT error?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s