[Design of JBossCache] - JBCACHE-880 discussion ...
by genman
I came with a new Eviction strategy. The idea is to allow users to "put" an expiration time into a Node, and the cache will then evict the node at that time.
I went ahead and commited the changes already, but I'm not 100% pleased yet.
The things that I am not happy with are:
1. I used "Long(timestamp)" as the expiration time. It would make more sense ot have expiration indicated with a java.util.Date instead, except Date is a (little) heavier and not constant.
2. Most of the time, users want to use a relative time, e.g. 10 seconds or 10 days.
3. Expiration is indicated with a String field "expiration". (Although it's configurable, I don't see why people would want to change this.) Getting this string constant out results in code that looks kind of crappy.
Ideally, it would be better to have an API, such as:
Node.setTimeToLive(int amount, TimeUnit unit);
If this were Ruby, I'd add this method to the object at runtime. :-)
Anyway, perhaps this belongs in a Util class or a static method on some existing class? Thoughts?
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3989165#3989165
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3989165
19 years, 4 months
[Design of EJB 3.0] - Problems with replicating entity queries via JBC
by bstansberry@jboss.com
Using JBC as a 2nd level cache leads to problems deserializing user classes when the Hibernate query cache is enabled. See http://jira.jboss.com/jira/browse/JBCLUSTER-150 for details.
This is really a JBC/Hibernate issue, although workarounds are possible in EJB3. Since any solution impacts EJB3, and any very short term workaround (i.e. for a December stacks release) is only possible in EJB3, I'm discussing the issue here.
Issue is JBC's classloader is from server/all/lib, and thus can't see and deserialize classes that are loaded from deploy. Deserialization happens when Hibernate's use of JBC as 2nd level cache causes replication. Specifically:
1) The Hibernate query cache is used. Here a user class could end up being used as an argument in a query. Hibernate replicates the actual query as the part of the FQN of a node in JBC.
2) A custom class is used as a field in an entity, and its not mapped as a component, but rather Hibernate treates it as a BLOB. The custom class would be replicated. (I haven't actually confirmed this failure mode, but it quite likely exists.)
Solutions:
A) Register a classloader with JBC for a region of the cache. JBC exposes an API to allow this to happen. The Hibernate/JBC integration code (part of Hibernate) can be updated to take advantage of this API. Hibernate already has the logical concept of different cache regions; the integration code can be updated to register the thread context classloader with JBC when a region is created.
EJB3 already partially overrides the standard Hibernate/JBC integration code, so as a short term workaround it's possible to fix this in EJB3, pending a later Hibernate release with this fixed.
Problems with solution A):
i) Hibernate has a "default" query cache region that will be shared by all queries that don't specifically name a region. There is no foolproof way to assign a specific classloader to this region, since it's storing to a JBC instance that may be shared between multiple EJB deployments. The cache region can be specified by users, although it's ugly:
| @Entity
| @Cache (usage=CacheConcurrencyStrategy.TRANSACTIONAL)
| @NamedQueries({
| @NamedQuery(name="account.highbalance.default",query="select account.balance from Account as account where account.accountHolder = ?1 and account.balance > ?2"),
| @NamedQuery(name="account.highbalance.namedregion",query="select account.balance from Account as account where account.accountHolder = ?1 and account.balance > ?2",
| hints={@QueryHint(name="org.hibernate.cacheRegion",value="AccountRegion")})
| })
| public class Account implements Serializable
| {
| ...
| }
|
The second query above uses the named region.
ii) With the query cache, the custom class is actually part of the Fqn of a JBC node, rather than part of its data map. I realized over the weekend that the existing JBC code for handling region-based classloaders doesn't handle custom classes in an Fqn. JIRA to remove this limitation is http://jira.jboss.com/jira/browse/JBCACHE-876, which should be pretty straightforward. But, fixing it requires JBC 1.4.1.GA, which is likely at least a couple weeks away.
Bringing us to solution..
B) Don't replicate the query cache.
Hibernate provides a hook to specifying the factory class used to set up any query cache. In persistence.xml we can specify a custom query cache factory that integrates with JBC, but which instructs JBC not to replicate any writes for that region of the cache. Thus the query cache is a local only cache, while entities are replicated. Hibernate also has an "UpdateTimestampsCache", which is used to trigger invalidations of query cache entries. AFAIK, there is no replication problem with this cache, and it needs to remain replicated.
I've pinged the Hibernate guys re: any issues w/ not replicating the query cache.
Solution B can also be implemented in the EJB3 code base pending a better solution in a Hibernate release. If there is an immediate requirement to get a workaround for this problem, it's the only way I see to go.
Another long term possibility is solution...
C) Like A), but now we create one JBC entity cache per deployment (i.e. per Hibernate session factory) rather than a single shared cache. This avoids the problem of deciding what classloader to use for the "default" query cache -- there's only one classloader per cache instance. With the JGroups multiplexer, having numerous JBC instances is a workable option. But going this route requires more thought.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3989163#3989163
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3989163
19 years, 4 months