Another question is when and where should I call the wrapper.delExpiryPolicy. currently, I haven't found the right place.
------------------ Original ------------------ From: "Lin";<[email protected]>; Date: Wed, Dec 2, 2015 10:06 AM To: "user"<[email protected]>; Subject: Re: Can I set an expiry policy for some specify entry? Hi Anton, I have tried to create some expiry polices for different entries, and during the testing, I found that I may have to hack some of the kernel codes of Ignite. Am I right? Here is my hacking and test case. Any suggestions are welcome. My wrapper implementation, public class KeyValueExpiryPolicyWrapper implements ExpiryPolicy, Serializable { // store the default policy private ExpiryPolicy defaultPolicy; // the policy for specified entries keys private Map<Object, ExpiryPolicy> expiryPolicyMap; public KeyValueExpiryPolicyWrapper(){ defaultPolicy = null; expiryPolicyMap = new HashMap<>(); } public void addExpiryPolicy(Object key, ExpiryPolicy policy) { if (null != key) expiryPolicyMap.put(key, policy); } public void delExpiryPolicy(Object key) { if (null != key) expiryPolicyMap.remove(key); } @Override public Duration getExpiryForCreation() { return null == defaultPolicy ? null : defaultPolicy.getExpiryForCreation(); } @Override public Duration getExpiryForAccess() { return null == defaultPolicy ? null : defaultPolicy.getExpiryForAccess(); } @Override public Duration getExpiryForUpdate() { return null == defaultPolicy ? null : defaultPolicy.getExpiryForUpdate(); } public Duration forAccess(Object key) { A.notNull(key, "key is undefined."); ExpiryPolicy policy = expiryPolicyMap.get(key); System.out.println("KeyValueExpiryPolicyWrapper.forAccess, map = " + expiryPolicyMap); System.out.println("KeyValueExpiryPolicyWrapper.forAccess with key=" + key + "" + ", policy = " + policy); if (null == policy) { policy = defaultPolicy; } return null == policy ? null : policy.getExpiryForAccess(); } public Duration forCreation(Object key) { A.notNull(key, "key is undefined."); ExpiryPolicy policy = expiryPolicyMap.get(key); System.out.println("KeyValueExpiryPolicyWrapper.forCreation, map = " + expiryPolicyMap); System.out.println("KeyValueExpiryPolicyWrapper.forCreation with key=" + key + "" + ", policy = " + policy); if (null == policy) { policy = defaultPolicy; } return null == policy ? null : policy.getExpiryForCreation(); } public Duration forUpdate(Object key) { A.notNull(key, "key is undefined."); ExpiryPolicy policy = expiryPolicyMap.get(key); System.out.println("KeyValueExpiryPolicyWrapper.forUpdate, map = " + expiryPolicyMap); System.out.println("KeyValueExpiryPolicyWrapper.forUpdate with key=" + key + "" + ", policy = " + policy); if (null == policy) { policy = defaultPolicy; } return null == policy ? null : policy.getExpiryForUpdate(); } } My hacking on GridCacheAdapter.java 1. hacking on org.apache.ignite.internal.processors.cache.GridCacheAdapter#expiryPolicy one parameter on entry's key is added. /** * Get the expiry policy for given key. If key is null, return the default policy. * @param plc Explicitly specified expiry policy for cache operation. * @param key the key of the entry * @return Expiry policy wrapper. */ @Nullable public IgniteCacheExpiryPolicy expiryPolicy(@Nullable ExpiryPolicy plc, @Nullable Object key) { if (plc == null) plc = ctx.expiry(); return CacheExpiryPolicy.forPolicy(plc, key); } 2. hacking on org.apache.ignite.internal.processors.cache.GridCacheAdapter.CacheExpiryPolicy *. one function `getRealkey` is added *. modify the implementations of forPolicy // get the entry's key private static Object getRealKey(@Nullable final Object key){ Object key0 = key; if (null != key) { if (key instanceof KeyCacheObjectImpl){ // TODO(jackeylv) currently, we can only solve the type of KeyCacheObjectImpl key0 = ((KeyCacheObjectImpl) key).val; } } return key0; }/** * @param expiryPlc Expiry policy. * @param key * @return Access expire policy. */ @Nullable private static CacheExpiryPolicy forPolicy(@Nullable final ExpiryPolicy expiryPlc, @Nullable final Object key) { if (expiryPlc == null) return null; return new CacheExpiryPolicy() { @Override public long forAccess() { if (null == key) return CU.toTtl(expiryPlc.getExpiryForAccess()); // added operation for polices wrapper. if (expiryPlc instanceof KeyValueExpiryPolicyWrapper){ return CU.toTtl(((KeyValueExpiryPolicyWrapper) expiryPlc).forAccess(getRealKey(key))); } System.err.println("forAccess,Key " + key + " given, by type error on expiryPlc " + expiryPlc); return CU.toTtl(expiryPlc.getExpiryForAccess()); } @Override public long forCreate() { if (null == key) return CU.toTtl(expiryPlc.getExpiryForCreation()); if (expiryPlc instanceof KeyValueExpiryPolicyWrapper){ return CU.toTtl(((KeyValueExpiryPolicyWrapper) expiryPlc).forCreation(getRealKey(key))); } System.err.println("forCreate, Key " + key + " given, by type error on expiryPlc " + expiryPlc); return CU.toTtl(expiryPlc.getExpiryForCreation()); } @Override public long forUpdate() { if (null == key) return CU.toTtl(expiryPlc.getExpiryForUpdate()); if (expiryPlc instanceof KeyValueExpiryPolicyWrapper){ return CU.toTtl(((KeyValueExpiryPolicyWrapper) expiryPlc).forUpdate(getRealKey(key))); } System.err.println("forUpdate, Key " + key + " given, by type error on expiryPlc " + expiryPlc); return CU.toTtl(expiryPlc.getExpiryForUpdate()); } }; } The test case, public class ExpiryExample { public static void test(Ignite ignite) { IgniteCache cache = ignite.getOrCreateCache("ExpiryExample"); String k1 = "k1"; // k1 with given expiry policy String k2 = "k2"; // k2 with default expiry policy String v1 = "v1"; String v2 = "v2"; // A policies wrapper KeyValueExpiryPolicyWrapper plc = new KeyValueExpiryPolicyWrapper(); plc.addExpiryPolicy(k1, new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS,3))); cache = cache.withExpiryPolicy(plc); cache.put(k1, v1); cache.put(k2, v2); String result = (String) cache.get(k1); System.out.println("ExpiryExample.main with k1 value = [" + result + "]"); A.ensure(v1.equals(result), "get failed with "+result); result = (String) cache.get(k2); System.out.println("ExpiryExample.main with k2 value = [" + result + "]"); A.ensure(v2.equals(result), "get failed with "+result); // sleep for a while to make sure the k1-v1 entry expired. try { TimeUnit.SECONDS.sleep(6); } catch (InterruptedException e) { e.printStackTrace(); return; } // test the expired results. result = (String)cache.get(k1); System.out.println("ExpiryExample.main with k1 value = [" + result + "]"); A.ensure(null == result, "cache entry not expired with "+result); result = (String)cache.get(k2); System.out.println("ExpiryExample.main with k2 value = [" + result + "]"); A.ensure(v2.equals(result), "cache entry not right with "+result); } } Currently, the simple test case is passed, but I am still worry about the hacking, because there are still some questions need to be answered. 1. any better solutions then this one? 2. this solution changed the org.apache.ignite.internal.processors.cache.GridCacheAdapter#expiryPolicy, and some situation like getAll or other batching operations, there are more than one keys in a request, and the expiry polices may be different for different keys. How to solve it? 3. is there any pitfall in this solution? Regards, Lin. ------------------ Original ------------------ From: "Anton Vinogradov";<[email protected]>; Date: Tue, Dec 1, 2015 10:01 PM To: "user"<[email protected]>; Subject: Re: Can I set an expiry policy for some specify entry? Lin, As you can see at example you can use cache.withExpiryPolicy() to gain cache wrapper with specific ExpiryPolicy. This policy will be used during operations on this cache wrapper, only. You can create as much wrappers as you need and put/get/etc entries using them. I recomend you to use CreatedExpiryPolicy to set ExpiryPolicy at entry creation. Comparision of ExpiryPolicies can be found here https://apacheignite.readme.io/v1.4/docs/expiry-policies Please have a look to other ExpiryPolicies, possible they will be more suitable to your solution. For example TouchedExpiryPolicy will renew timeout at each operation on entry. On Tue, Dec 1, 2015 at 3:33 PM, Vladimir Ershov <[email protected]> wrote: Hi Lin, An expiry policy is working for all values, which were added through cacheWithExpiryPolicy according to the next example: IgniteCache<Object, Object> cacheWithExpiryPolicy = cache.withExpiryPolicy( new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS, 5))); You are welcome to find an explaining example in the end of this message. It is also possible, that actually you are looking for something like eviction policy. Please take a look here then: https://apacheignite.readme.io/v1.5/docs/evictions Please, provide the feedback, if this answer was useful, or not. Thanks! public void test() throws Exception { Ignite ignite = startGrid(0); // some starting util method CacheConfiguration<Integer, Integer> cfg = new CacheConfiguration<>(); cfg.setName(CACHE); cfg.setCacheMode(CacheMode.PARTITIONED); cfg.setRebalanceMode(CacheRebalanceMode.SYNC); cfg.setBackups(1); ignite.getOrCreateCache(cfg); IgniteCache<Object, Object> cache1 = ignite.cache(null); IgniteCache<Object, Object> cache2 = cache1.withExpiryPolicy( new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS, 1))); cache1.put(1, 1); cache1.put(2, 2); cache2.put(3, 3); cache2.get(1); // Does not affect ExpiryPolicy. U.sleep(2000); assert cache1.get(1) == 1; assert cache2.get(1) == 1; // not Expired assert cache1.get(2) == 2; assert cache1.get(3) == null; // Expired. } On Tue, Dec 1, 2015 at 10:47 AM, Lin <[email protected]> wrote: Hi, I have read the docs on jcache expiry policies, the policy will be used for each operation invoked on the returned cache instance. IgniteCache<Object, Object> cache = cache.withExpiryPolicy( new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS, 5))); and searched the nabble faq and found http://apache-ignite-users.70518.x6.nabble.com/Does-IgniteCache-withExpiryPolicy-affect-existing-cache-entries-td1870.html As I know, the expiry policy is worked for all the entries in the cache. I would like to specify different expiry policies for some different entries, How can I do? Thanks for you help. Regards, Lin
