interesting bug fixed in version 4.38

20 views
Skip to first unread message

Gray Watson

unread,
Mar 23, 2012, 10:53:34 AM3/23/12
to
Just pushed out a new release announcement for 4.38. Filipe Leandro and I worked interactively for like 10 hours last night to find and fix it -- thanks much dude. It was a very subtle interaction between the object cache, foreign collections, and the way Android manages its connections internally. I'm sending this out to all of the mailing lists because I think there are some general lessons about "session" management around object caches. This bug has been there since the object caches have been added.

Filipe's application would worked fine when initially run but if he popped back out of it and then immediately ran it again, it would throw "database ... already closed" exceptions. Because the application destroyed all of its views, the underlying helper and database would be closed when the main view was left. He was using the inner static object cache, and because the application was still resident, the cache still had objects. Since ForeignCollections have an inner DAO reference, when he ran the application again, any reference to the foreign collections (especially if lazy) would reference the closed database -- not the re-opened one. ORMLite now automatically flushes all of static object caches (and the DaoManager) when the helper is reconstructed. If you have are constructing your own caches you must make sure they are cleared in the main view onCreate().

But I think there is an interesting warning that needs to be understood and could affect JDBC users as well. If you are using object caches, especially the static inner one, you must clear them if you create another ConnectionSource to another database shard or something that you clear the object caches. To clear the static cache you can do:

BaseDoaImpl.clearAllInternalObjectCaches();

Comments? Questions?
gray

ido

unread,
Feb 3, 2013, 7:34:21 AM2/3/13
to ormli...@googlegroups.com
I have a question regarding the static inner object cache:
Shouldn't it be per connectionSource?

We are using different connections to access different databases, and have started encountering problems with the object cache when switching between those connections.
As each connection uses a different set of Dao objects (based on the same classes), we've assumed that the object cache will be different per database.
It seems like this is not the cache, as the static inner object cache (which is used by default) contains a map from the clazz and have no reference to the connection.
This means that the cache for one connection might return objects which should be visible from another connection only.

This might also explain a few issues we've encountered while trying to use the objectCache while using 2  connections - one for background analysis which issued a long write transaction, and another for display, which issued read queries and sometimes received objects as they appear in the transaction and not as they appear in the database (which is what we expected).

Is this the required behavior?
Is there a solution for our use-case that doesn't require us to manage the object caches by ourselves?

Thank you,
Ido

Gray Watson

unread,
Feb 3, 2013, 9:58:30 AM2/3/13
to ormli...@googlegroups.com
On Feb 3, 2013, at 7:34 AM, ido wrote:

> I have a question regarding the static inner object cache: Shouldn't it be per connectionSource?

Ah, interesting. The DAO is per connectionSource which is why the DaoManager uses connection-source to generate the DAOs. Since the DAO is what holds the cache, I would have thought that the cache then would have been per connectionSource as well.

However, if you use the Dao.setObjectCache(boolean) method, this is going to use a static ObjectCache which is just by Class -- not by Class/Connection-Source. You can certainly create your own cache -- one for each of your connection-sources -- and then set it on the DAO yourself:

dao.setObjectCache(ReferenceObjectCache.makeWeakCache());

Have you tried this Ido? Let me know if it resolves your problems.

> Is there a solution for our use-case that doesn't require us to manage the object caches by ourselves?

I don't think so. Since this use pattern is, I assume, somewhat rare I'm less interested in complicating the object class by making all lookups by class/connection-source.

Anyone else want to comment here?
gray

ido

unread,
Feb 3, 2013, 11:03:43 AM2/3/13
to ormli...@googlegroups.com
Thank you for the quick response.
Setting the object cache by myself indeed solved this issue.

I just want to mention a more common use pattern where this problem might arise - using a transaction for a complex calculation.
The problem also occurs when opening two connections - one for a transaction, and one for retrieving information.
In my test case, I've opened 2 threads - one for analysis, and one for data retrieval, each using their own connection.
The analysis thread creates a new object (with id 1) inside a transaction, and then sleeps for 10 seconds, and the other thread tries to retrieve an object with the id (1).
Since the (default) object-cache is shared between the connections, the read thread is able to receive the object although it shouldn't be able to until the transaction is commited.
Reply all
Reply to author
Forward
0 new messages